Spaces:
Running
Running
File size: 4,372 Bytes
29a56dd d0d9535 29a56dd d0d9535 7de3bfe 29a56dd de80961 29a56dd de80961 29a56dd de80961 29a56dd de80961 29a56dd |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
"""
Streamlit File Extension Renamer
--------------------------------
A lightweight Streamlit app intended for deployment on Hugging Face Spaces.
The app lets users upload one or more files and rename (not convert) their
extensions to any common file-type extension the user selects. Executable
and binary files are blocked for security reasons.
"""
from __future__ import annotations
import io
import zipfile
from datetime import datetime
from pathlib import Path
import streamlit as st
# -----------------------------------------------------------------------------
# Configuration
# -----------------------------------------------------------------------------
# List of target extensions displayed to the user. Extend this list as needed.
ALLOWED_TARGET_EXTS: list[str] = [
".txt",
".pdf",
".doc",
".docx",
".json",
".csv",
".xml",
".html",
".css",
".js",
".md",
".jpg",
".jpeg",
".png",
".gif",
".bmp",
".tiff",
".svg",
".ico",
".mp3",
".wav",
".mp4",
".avi",
".mkv",
".mov",
".zip",
".tar",
".gz",
".7z",
]
# Source‐file extensions that are disallowed (will be skipped if uploaded).
DISALLOWED_SOURCE_EXTS: set[str] = {".exe", ".bin"}
# -----------------------------------------------------------------------------
# UI helpers
# -----------------------------------------------------------------------------
def make_sidebar() -> str:
"""Return the user-chosen target extension from sidebar controls."""
st.sidebar.header("Settings")
target_ext = st.sidebar.selectbox(
label="Target extension (applied to **all** uploaded files)",
options=ALLOWED_TARGET_EXTS,
index=ALLOWED_TARGET_EXTS.index(".pdf"),
)
st.sidebar.markdown(
"""❗ **Note**: This tool only renames the file extension. It does **not**
convert the underlying file format. Opening a renamed file with an
incompatible program may fail or lead to data corruption."""
)
return target_ext
def make_uploader():
"""Return the list of files uploaded by the user."""
return st.file_uploader(
"Upload one or more files",
accept_multiple_files=True,
type=[ext.lstrip(".") for ext in ALLOWED_TARGET_EXTS],
help="Drag-and-drop or browse for files to rename.",
)
# -----------------------------------------------------------------------------
# Core logic
# -----------------------------------------------------------------------------
def write_zip(uploaded_files: list[st.runtime.uploaded_file_manager.UploadedFile], target_ext: str) -> io.BytesIO:
"""Return an in-memory ZIP archive of the uploaded files with the new extension."""
buffer = io.BytesIO()
with zipfile.ZipFile(buffer, "w", zipfile.ZIP_DEFLATED) as zf:
for file in uploaded_files:
orig_path = Path(file.name)
if orig_path.suffix.lower() in DISALLOWED_SOURCE_EXTS:
st.warning(f"⏭️ Skipping disallowed file: **{orig_path.name}**")
continue
renamed = orig_path.with_suffix(target_ext)
zf.writestr(renamed.name, file.read())
st.success(f"✅ Renamed **{orig_path.name}** → **{renamed.name}**")
buffer.seek(0)
return buffer
# -----------------------------------------------------------------------------
# Main app
# -----------------------------------------------------------------------------
def main() -> None:
st.set_page_config("Extension Renamer", page_icon="📄", layout="centered")
st.title("📄 Universal File-Extension Renamer")
st.write(
"Upload files, choose a new extension, and download them renamed in a single ZIP archive."
)
target_ext = make_sidebar()
uploaded_files = make_uploader()
if uploaded_files and st.button("🔄 Rename & Package"):
zip_buffer = write_zip(uploaded_files, target_ext)
timestamp = datetime.utcnow().strftime("%Y%m%dT%H%M%SZ")
st.download_button(
label="⬇️ Download ZIP",
data=zip_buffer,
file_name=f"renamed_{timestamp}.zip",
mime="application/zip",
)
st.caption("© 2025 File-Extension Renamer • Built with Streamlit • Deployed on Hugging Face Spaces")
if __name__ == "__main__":
main()
|