import streamlit as st import os import zipfile from pathlib import Path import tempfile import shutil def is_safe_extension(extension): """Check if the extension is safe to convert to""" dangerous_extensions = ['.exe', '.bin', '.bat', '.cmd', '.com', '.scr', '.pif', '.vbs', '.js'] return extension.lower() not in dangerous_extensions def change_file_extension(file_content, original_name, new_extension): """Change file extension and return new filename""" # Remove the dot if user includes it if new_extension.startswith('.'): new_extension = new_extension[1:] # Get the base name without extension base_name = Path(original_name).stem # Create new filename new_filename = f"{base_name}.{new_extension}" return new_filename, file_content def create_download_zip(files_data): """Create a zip file containing all converted files""" # Create a temporary directory with tempfile.TemporaryDirectory() as temp_dir: zip_path = os.path.join(temp_dir, "converted_files.zip") with zipfile.ZipFile(zip_path, 'w') as zipf: for filename, content in files_data: zipf.writestr(filename, content) # Read the zip file content with open(zip_path, 'rb') as f: zip_content = f.read() return zip_content def main(): st.set_page_config( page_title="File Extension Converter", page_icon="🔄", layout="wide" ) st.title("🔄 File Extension Converter") st.markdown("Convert any file extension to another (safely)") # Sidebar with instructions with st.sidebar: st.header("📋 Instructions") st.markdown(""" 1. Upload one or more files 2. Enter the target extension 3. Download converted files **Safety Note:** - .exe and .bin files are blocked for security - Only the extension is changed, not the file content """) st.header("⚠️ Blocked Extensions") st.code(".exe, .bin, .bat, .cmd, .com, .scr, .pif, .vbs, .js") # Main interface col1, col2 = st.columns([2, 1]) with col1: st.header("Upload Files") uploaded_files = st.file_uploader( "Choose files to convert", accept_multiple_files=True, help="Upload any files you want to change the extension for" ) with col2: st.header("Target Extension") new_extension = st.text_input( "New extension", placeholder="e.g., txt, pdf, jpg", help="Enter the extension you want to convert to (without the dot)" ).strip() if uploaded_files and new_extension: # Validate extension if new_extension.startswith('.'): new_extension = new_extension[1:] full_extension = f".{new_extension}" if not is_safe_extension(full_extension): st.error(f"❌ Extension '{full_extension}' is not allowed for security reasons") return st.success(f"✅ Converting to: **{full_extension}**") # Process files converted_files = [] results_data = [] st.header("📁 Conversion Results") for uploaded_file in uploaded_files: original_name = uploaded_file.name file_content = uploaded_file.read() # Convert extension new_filename, new_content = change_file_extension( file_content, original_name, new_extension ) converted_files.append((new_filename, new_content)) # Display result col_orig, col_arrow, col_new = st.columns([3, 1, 3]) with col_orig: st.text(f"📄 {original_name}") with col_arrow: st.text("➡️") with col_new: st.text(f"📄 {new_filename}") st.divider() # Download options st.header("💾 Download") if len(converted_files) == 1: # Single file download filename, content = converted_files[0] st.download_button( label=f"📥 Download {filename}", data=content, file_name=filename, mime="application/octet-stream" ) else: # Multiple files - create zip zip_content = create_download_zip(converted_files) st.download_button( label=f"📥 Download All Files ({len(converted_files)} files)", data=zip_content, file_name="converted_files.zip", mime="application/zip" ) st.info(f"💡 {len(converted_files)} files will be downloaded as a ZIP archive") elif uploaded_files and not new_extension: st.warning("⚠️ Please enter a target extension") elif new_extension and not uploaded_files: st.warning("⚠️ Please upload files to convert") # Footer st.divider() st.markdown("""
Built with Streamlit 🎈 | Safe file extension conversion
""", unsafe_allow_html=True) if __name__ == "__main__": main()