| import gradio as gr |
| import os |
| import zipfile |
| import tempfile |
| import shutil |
| from pathlib import Path |
| import mimetypes |
|
|
| |
| UPLOADS_FOLDER = "uploads" |
| os.makedirs(UPLOADS_FOLDER, exist_ok=True) |
|
|
| def process_file(file_obj, file_name, action): |
| """ |
| Process uploaded file: return original or create zip |
| """ |
| if not file_obj: |
| return None, "❌ No file uploaded" |
| |
| try: |
| |
| temp_dir = tempfile.mkdtemp() |
| original_path = os.path.join(temp_dir, file_name or os.path.basename(file_obj.name)) |
| |
| |
| shutil.copy2(file_obj.name, original_path) |
| |
| if action == "original": |
| |
| return original_path, f"✅ Ready to download: {os.path.basename(original_path)}" |
| |
| elif action == "zip": |
| |
| base_name = os.path.splitext(os.path.basename(original_path))[0] |
| zip_path = os.path.join(temp_dir, f"{base_name}.zip") |
| |
| with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: |
| zipf.write(original_path, os.path.basename(original_path)) |
| |
| return zip_path, f"✅ Zipped as: {os.path.basename(zip_path)}" |
| |
| elif action == "zip_with_password": |
| |
| try: |
| import pyminizip |
| base_name = os.path.splitext(os.path.basename(original_path))[0] |
| zip_path = os.path.join(temp_dir, f"{base_name}_protected.zip") |
| |
| |
| pyminizip.compress( |
| original_path, |
| None, |
| zip_path, |
| "password123", |
| 5 |
| ) |
| return zip_path, f"✅ Password-protected zip created (password: password123)" |
| |
| except ImportError: |
| return None, "❌ pyminizip not installed. Install with: pip install pyminizip" |
| |
| else: |
| return None, "❌ Invalid action selected" |
| |
| except Exception as e: |
| return None, f"❌ Error: {str(e)}" |
|
|
| def process_multiple_files(files, action): |
| """ |
| Process multiple uploaded files |
| """ |
| if not files: |
| return None, "❌ No files uploaded" |
| |
| try: |
| temp_dir = tempfile.mkdtemp() |
| |
| if action == "individual": |
| |
| zip_path = os.path.join(temp_dir, "files.zip") |
| |
| with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: |
| for file_obj in files: |
| file_path = file_obj.name |
| zipf.write(file_path, os.path.basename(file_path)) |
| |
| return zip_path, f"✅ Created zip with {len(files)} files" |
| |
| elif action == "separate": |
| |
| zip_path = os.path.join(temp_dir, "separate_files.zip") |
| |
| with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf: |
| for file_obj in files: |
| file_path = file_obj.name |
| |
| individual_zip = os.path.join(temp_dir, f"{os.path.splitext(os.path.basename(file_path))[0]}.zip") |
| with zipfile.ZipFile(individual_zip, 'w', zipfile.ZIP_DEFLATED) as ind_zip: |
| ind_zip.write(file_path, os.path.basename(file_path)) |
| |
| zipf.write(individual_zip, os.path.basename(individual_zip)) |
| |
| return zip_path, f"✅ Created zip with {len(files)} individual zips" |
| |
| else: |
| return None, "❌ Invalid action selected" |
| |
| except Exception as e: |
| return None, f"❌ Error: {str(e)}" |
|
|
| def get_file_info(file_obj): |
| """Get information about uploaded file""" |
| if not file_obj: |
| return "No file selected" |
| |
| try: |
| file_path = file_obj.name |
| file_size = os.path.getsize(file_path) |
| file_ext = os.path.splitext(file_path)[1].lower() |
| |
| |
| mime_type, _ = mimetypes.guess_type(file_path) |
| file_type = mime_type.split('/')[0] if mime_type else "Unknown" |
| |
| info = f""" |
| 📄 **File Information:** |
| |
| **Name:** {os.path.basename(file_path)} |
| **Size:** {file_size:,} bytes ({file_size/1024:.2f} KB) |
| **Extension:** {file_ext} |
| **Type:** {file_type} |
| **Path:** {file_path} |
| """ |
| |
| return info |
| |
| except Exception as e: |
| return f"❌ Error getting file info: {str(e)}" |
|
|
| |
| with gr.Blocks(title="File Upload & Download Manager", theme=gr.themes.Soft()) as iface: |
| |
| gr.Markdown("# 📁 File Upload & Download Manager") |
| gr.Markdown("Upload files and download them as original or zipped") |
| |
| with gr.Tabs(): |
| |
| with gr.Tab("Single File"): |
| with gr.Row(): |
| with gr.Column(scale=2): |
| single_file = gr.File( |
| label="Upload a File", |
| file_count="single" |
| ) |
| |
| file_name_input = gr.Textbox( |
| label="Custom Filename (optional)", |
| placeholder="Leave empty to keep original name...", |
| info="Enter a custom name for the downloaded file" |
| ) |
| |
| single_action = gr.Radio( |
| choices=[ |
| ("Download Original", "original"), |
| ("Download as ZIP", "zip"), |
| ("Password-protected ZIP", "zip_with_password") |
| ], |
| label="Select Action", |
| value="original" |
| ) |
| |
| single_btn = gr.Button("Process File", variant="primary") |
| |
| with gr.Column(scale=1): |
| file_info = gr.Markdown(label="File Information") |
| single_status = gr.Textbox(label="Status", interactive=False) |
| single_download = gr.File(label="Download Processed File", interactive=False) |
| |
| |
| single_file.change( |
| fn=get_file_info, |
| inputs=[single_file], |
| outputs=file_info |
| ) |
| |
| |
| with gr.Tab("Multiple Files"): |
| with gr.Row(): |
| with gr.Column(scale=2): |
| multi_files = gr.File( |
| label="Upload Multiple Files", |
| file_count="multiple", |
| file_types=["image", "video", "audio", "text", "pdf", ".zip"] |
| ) |
| |
| multi_action = gr.Radio( |
| choices=[ |
| ("Combine all files into one ZIP", "individual"), |
| ("Create separate ZIPs for each file", "separate") |
| ], |
| label="Select Action", |
| value="individual" |
| ) |
| |
| multi_btn = gr.Button("Process Files", variant="primary") |
| |
| with gr.Column(scale=1): |
| multi_status = gr.Textbox(label="Status", interactive=False) |
| multi_download = gr.File(label="Download Processed Files", interactive=False) |
| |
| |
| with gr.Tab("Batch Processing"): |
| with gr.Row(): |
| with gr.Column(): |
| gr.Markdown("### Upload Multiple Files for Batch Processing") |
| |
| batch_files = gr.File( |
| label="Upload Files", |
| file_count="multiple", |
| file_types=None |
| ) |
| |
| batch_options = gr.CheckboxGroup( |
| choices=[ |
| "Create individual ZIPs", |
| "Create combined ZIP", |
| "Rename with timestamp", |
| "Add to existing ZIP" |
| ], |
| label="Processing Options", |
| value=["Create combined ZIP"] |
| ) |
| |
| with gr.Row(): |
| batch_format = gr.Dropdown( |
| choices=[".zip", ".7z", ".tar.gz"], |
| value=".zip", |
| label="Archive Format" |
| ) |
| |
| compression_level = gr.Slider( |
| minimum=1, |
| maximum=9, |
| value=6, |
| step=1, |
| label="Compression Level" |
| ) |
| |
| batch_btn = gr.Button("Process Batch", variant="primary", size="lg") |
| |
| with gr.Column(): |
| batch_status = gr.Textbox(label="Status", interactive=False, lines=3) |
| batch_download = gr.File(label="Download Results", interactive=False) |
| |
| |
| with gr.Accordion("📖 Instructions & Features", open=False): |
| gr.Markdown(""" |
| ## How to Use: |
| |
| ### Single File Tab: |
| 1. **Upload** a single file |
| 2. (Optional) Enter a custom filename |
| 3. **Choose action**: Download original, as ZIP, or password-protected ZIP |
| 4. Click **Process File** |
| |
| ### Multiple Files Tab: |
| 1. **Upload** multiple files (Ctrl+Click to select multiple) |
| 2. **Choose action**: Combine into one ZIP or create separate ZIPs |
| 3. Click **Process Files** |
| |
| ### Batch Processing Tab: |
| 1. **Upload** multiple files |
| 2. **Select processing options** |
| 3. Choose archive format and compression level |
| 4. Click **Process Batch** |
| |
| ## Features: |
| - ✅ Single file upload and download |
| - ✅ Multiple file upload and batch processing |
| - ✅ ZIP file creation with compression |
| - ✅ Password-protected ZIPs (requires pyminizip) |
| - ✅ File information display |
| - ✅ Custom filename support |
| - ✅ Multiple archive formats |
| |
| ## Notes: |
| - Files are processed in temporary storage |
| - Original files are not modified |
| - Large files may take time to process |
| - Password for protected ZIPs: `password123` |
| """) |
| |
| |
| single_btn.click( |
| fn=process_file, |
| inputs=[single_file, file_name_input, single_action], |
| outputs=[single_download, single_status] |
| ) |
| |
| multi_btn.click( |
| fn=process_multiple_files, |
| inputs=[multi_files, multi_action], |
| outputs=[multi_download, multi_status] |
| ) |
| |
| |
| def process_batch(files, options, format_type, compression): |
| if not files: |
| return None, "❌ No files uploaded" |
| |
| try: |
| temp_dir = tempfile.mkdtemp() |
| results = [] |
| |
| |
| if "Create combined ZIP" in options: |
| zip_name = f"combined{format_type}" |
| zip_path = os.path.join(temp_dir, zip_name) |
| |
| if format_type == ".zip": |
| with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression) as zipf: |
| for file_obj in files: |
| file_path = file_obj.name |
| arcname = os.path.basename(file_path) |
| if "Rename with timestamp" in options: |
| import time |
| name, ext = os.path.splitext(arcname) |
| arcname = f"{name}_{int(time.time())}{ext}" |
| zipf.write(file_path, arcname) |
| results.append(zip_path) |
| |
| if "Create individual ZIPs" in options: |
| for file_obj in files: |
| file_path = file_obj.name |
| base_name = os.path.splitext(os.path.basename(file_path))[0] |
| if "Rename with timestamp" in options: |
| import time |
| base_name = f"{base_name}_{int(time.time())}" |
| |
| individual_zip = os.path.join(temp_dir, f"{base_name}{format_type}") |
| |
| if format_type == ".zip": |
| with zipfile.ZipFile(individual_zip, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression) as zipf: |
| zipf.write(file_path, os.path.basename(file_path)) |
| |
| results.append(individual_zip) |
| |
| |
| if len(results) > 1: |
| final_zip = os.path.join(temp_dir, f"batch_results{format_type}") |
| with zipfile.ZipFile(final_zip, 'w', zipfile.ZIP_DEFLATED) as zipf: |
| for result in results: |
| zipf.write(result, os.path.basename(result)) |
| output_file = final_zip |
| elif results: |
| output_file = results[0] |
| else: |
| return None, "⚠️ No processing options selected" |
| |
| return output_file, f"✅ Processed {len(files)} file(s) with {len(options)} option(s)" |
| |
| except Exception as e: |
| return None, f"❌ Error: {str(e)}" |
| |
| batch_btn.click( |
| fn=process_batch, |
| inputs=[batch_files, batch_options, batch_format, compression_level], |
| outputs=[batch_download, batch_status] |
| ) |
|
|
| |
| if __name__ == "__main__": |
| iface.launch( |
| server_name="127.0.0.1", |
| server_port=7861, |
| show_error=True, |
| share=False, |
| ssr_mode=False |
| ) |