zip / add.py
MySafeCode's picture
Create add.py
3ec1324 verified
import gradio as gr
import os
import zipfile
import tempfile
import shutil
from pathlib import Path
import mimetypes
import time
# 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:
# In Gradio 6+, file_obj is a dictionary
if isinstance(file_obj, dict):
file_path = file_obj["path"]
original_name = file_obj["name"]
else:
# Fallback for older versions
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
original_name = os.path.basename(file_path)
# Save uploaded file temporarily
temp_dir = tempfile.mkdtemp()
custom_name = file_name.strip() if file_name and file_name.strip() else original_name
original_path = os.path.join(temp_dir, custom_name)
# Copy file to temp location
shutil.copy2(file_path, original_path)
if action == "original":
# Return original file - just the path as string
return original_path, f"✅ Ready to download: {custom_name}"
elif action == "zip":
# Create zip file
base_name = os.path.splitext(custom_name)[0]
zip_name = f"{base_name}.zip"
zip_path = os.path.join(temp_dir, zip_name)
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
zipf.write(original_path, custom_name)
return zip_path, f"✅ Zipped as: {zip_name}"
elif action == "zip_with_password":
# Create password-protected zip
try:
import pyminizip
base_name = os.path.splitext(custom_name)[0]
zip_name = f"{base_name}_protected.zip"
zip_path = os.path.join(temp_dir, zip_name)
# 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_name = "files.zip"
zip_path = os.path.join(temp_dir, zip_name)
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_obj in files:
# Handle Gradio 6+ file object format
if isinstance(file_obj, dict):
file_path = file_obj["path"]
file_name = file_obj["name"]
else:
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
file_name = os.path.basename(file_path)
zipf.write(file_path, file_name)
return zip_path, f"✅ Created zip with {len(files)} files"
elif action == "separate":
# Create separate zips for each file
zip_name = "separate_files.zip"
zip_path = os.path.join(temp_dir, zip_name)
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_obj in files:
# Handle Gradio 6+ file object format
if isinstance(file_obj, dict):
file_path = file_obj["path"]
file_name = file_obj["name"]
else:
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
file_name = os.path.basename(file_path)
# Create individual zip first
base_name = os.path.splitext(file_name)[0]
individual_zip_name = f"{base_name}.zip"
individual_zip_path = os.path.join(temp_dir, individual_zip_name)
with zipfile.ZipFile(individual_zip_path, 'w', zipfile.ZIP_DEFLATED) as ind_zip:
ind_zip.write(file_path, file_name)
# Add individual zip to main zip
zipf.write(individual_zip_path, individual_zip_name)
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:
# Handle Gradio 6+ file object format
if isinstance(file_obj, dict):
file_path = file_obj["path"]
file_name = file_obj["name"]
else:
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
file_ext = os.path.splitext(file_name)[1].lower()
# Get file type
mime_type, _ = mimetypes.guess_type(file_path)
file_type = mime_type.split('/')[0] if mime_type else "Unknown"
# Get creation and modification times
ctime = time.ctime(os.path.getctime(file_path))
mtime = time.ctime(os.path.getmtime(file_path))
info = f"""
📄 **File Information:**
**Name:** {file_name}
**Size:** {file_size:,} bytes ({file_size/1024:.2f} KB)
**Extension:** {file_ext}
**Type:** {file_type}
**Created:** {ctime}
**Modified:** {mtime}
**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",
# Updated file_types format for Gradio 6+
file_types=[
"image", "video", "audio",
"text", ".pdf", ".zip", ".txt",
".doc", ".docx", ".xls", ".xlsx"
]
)
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`
- For Gradio 6+ compatibility, file objects are handled differently
""")
# 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:
# Handle Gradio 6+ file object format
if isinstance(file_obj, dict):
file_path = file_obj["path"]
arcname = file_obj["name"]
else:
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
arcname = os.path.basename(file_path)
if "Rename with timestamp" in options:
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:
# Handle Gradio 6+ file object format
if isinstance(file_obj, dict):
file_path = file_obj["path"]
file_name = file_obj["name"]
else:
file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
file_name = os.path.basename(file_path)
base_name = os.path.splitext(file_name)[0]
if "Rename with timestamp" in options:
base_name = f"{base_name}_{int(time.time())}"
individual_zip_name = f"{base_name}{format_type}"
individual_zip_path = os.path.join(temp_dir, individual_zip_name)
if format_type == ".zip":
with zipfile.ZipFile(individual_zip_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression) as zipf:
zipf.write(file_path, file_name)
results.append(individual_zip_path)
# If multiple results, create a final zip
if len(results) > 1:
final_zip_name = f"batch_results{format_type}"
final_zip_path = os.path.join(temp_dir, final_zip_name)
with zipfile.ZipFile(final_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for result_path in results:
zipf.write(result_path, os.path.basename(result_path))
output_file = final_zip_path
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 - SIMPLIFIED FOR HUGGING FACE SPACES
if __name__ == "__main__":
# For Hugging Face Spaces, use simple launch without port specification
iface.launch(
show_error=True,
share=False,
theme=gr.themes.Soft()
)