Spaces:
Running
Running
| import gradio as gr | |
| import os | |
| import zipfile | |
| import tempfile | |
| import shutil | |
| from pathlib import Path | |
| import mimetypes | |
| # Create uploads directory | |
| 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: | |
| # Save uploaded file temporarily | |
| temp_dir = tempfile.mkdtemp() | |
| original_path = os.path.join(temp_dir, file_name or os.path.basename(file_obj.name)) | |
| # Copy file to temp location | |
| shutil.copy2(file_obj.name, original_path) | |
| if action == "original": | |
| # Return original file | |
| return original_path, f"✅ Ready to download: {os.path.basename(original_path)}" | |
| elif action == "zip": | |
| # Create zip file | |
| 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": | |
| # Create password-protected zip (requires pyminizip) | |
| 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") | |
| # Compress with password | |
| pyminizip.compress( | |
| original_path, | |
| None, | |
| zip_path, | |
| "password123", # Default password | |
| 5 # Compression level | |
| ) | |
| 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": | |
| # Create zip containing all files | |
| 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": | |
| # Create separate zips for each file | |
| 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 | |
| # Create individual zip first | |
| 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)) | |
| # Add individual zip to main zip | |
| 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() | |
| # Get file type | |
| 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)}" | |
| # Create Gradio interface | |
| 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(): | |
| # Single File Tab | |
| 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) | |
| # Update file info when file is uploaded | |
| single_file.change( | |
| fn=get_file_info, | |
| inputs=[single_file], | |
| outputs=file_info | |
| ) | |
| # Multiple Files Tab | |
| 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) | |
| # Batch Processing Tab | |
| 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 # All file types | |
| ) | |
| 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) | |
| # Instructions | |
| 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` | |
| """) | |
| # Connect events | |
| 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] | |
| ) | |
| # Batch processing function | |
| def process_batch(files, options, format_type, compression): | |
| if not files: | |
| return None, "❌ No files uploaded" | |
| try: | |
| temp_dir = tempfile.mkdtemp() | |
| results = [] | |
| # Process based on options | |
| 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 multiple results, create a final 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] | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| iface.launch( | |
| server_name="127.0.0.1", | |
| server_port=7861, # Different port to avoid conflict | |
| show_error=True, | |
| share=False, | |
| ssr_mode=False | |
| ) |