MySafeCode commited on
Commit
3ec1324
·
verified ·
1 Parent(s): e7c1e8d

Create add.py

Browse files
Files changed (1) hide show
  1. add.py +446 -0
add.py ADDED
@@ -0,0 +1,446 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import zipfile
4
+ import tempfile
5
+ import shutil
6
+ from pathlib import Path
7
+ import mimetypes
8
+ import time
9
+
10
+ # Create uploads directory
11
+ UPLOADS_FOLDER = "uploads"
12
+ os.makedirs(UPLOADS_FOLDER, exist_ok=True)
13
+
14
+ def process_file(file_obj, file_name, action):
15
+ """
16
+ Process uploaded file: return original or create zip
17
+ """
18
+ if not file_obj:
19
+ return None, "❌ No file uploaded"
20
+
21
+ try:
22
+ # In Gradio 6+, file_obj is a dictionary
23
+ if isinstance(file_obj, dict):
24
+ file_path = file_obj["path"]
25
+ original_name = file_obj["name"]
26
+ else:
27
+ # Fallback for older versions
28
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
29
+ original_name = os.path.basename(file_path)
30
+
31
+ # Save uploaded file temporarily
32
+ temp_dir = tempfile.mkdtemp()
33
+ custom_name = file_name.strip() if file_name and file_name.strip() else original_name
34
+ original_path = os.path.join(temp_dir, custom_name)
35
+
36
+ # Copy file to temp location
37
+ shutil.copy2(file_path, original_path)
38
+
39
+ if action == "original":
40
+ # Return original file - just the path as string
41
+ return original_path, f"✅ Ready to download: {custom_name}"
42
+
43
+ elif action == "zip":
44
+ # Create zip file
45
+ base_name = os.path.splitext(custom_name)[0]
46
+ zip_name = f"{base_name}.zip"
47
+ zip_path = os.path.join(temp_dir, zip_name)
48
+
49
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
50
+ zipf.write(original_path, custom_name)
51
+
52
+ return zip_path, f"✅ Zipped as: {zip_name}"
53
+
54
+ elif action == "zip_with_password":
55
+ # Create password-protected zip
56
+ try:
57
+ import pyminizip
58
+ base_name = os.path.splitext(custom_name)[0]
59
+ zip_name = f"{base_name}_protected.zip"
60
+ zip_path = os.path.join(temp_dir, zip_name)
61
+
62
+ # Compress with password
63
+ pyminizip.compress(
64
+ original_path,
65
+ None,
66
+ zip_path,
67
+ "password123", # Default password
68
+ 5 # Compression level
69
+ )
70
+ return zip_path, f"✅ Password-protected zip created (password: password123)"
71
+
72
+ except ImportError:
73
+ return None, "❌ pyminizip not installed. Install with: pip install pyminizip"
74
+
75
+ else:
76
+ return None, "❌ Invalid action selected"
77
+
78
+ except Exception as e:
79
+ return None, f"❌ Error: {str(e)}"
80
+
81
+ def process_multiple_files(files, action):
82
+ """
83
+ Process multiple uploaded files
84
+ """
85
+ if not files:
86
+ return None, "❌ No files uploaded"
87
+
88
+ try:
89
+ temp_dir = tempfile.mkdtemp()
90
+
91
+ if action == "individual":
92
+ # Create zip containing all files
93
+ zip_name = "files.zip"
94
+ zip_path = os.path.join(temp_dir, zip_name)
95
+
96
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
97
+ for file_obj in files:
98
+ # Handle Gradio 6+ file object format
99
+ if isinstance(file_obj, dict):
100
+ file_path = file_obj["path"]
101
+ file_name = file_obj["name"]
102
+ else:
103
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
104
+ file_name = os.path.basename(file_path)
105
+
106
+ zipf.write(file_path, file_name)
107
+
108
+ return zip_path, f"✅ Created zip with {len(files)} files"
109
+
110
+ elif action == "separate":
111
+ # Create separate zips for each file
112
+ zip_name = "separate_files.zip"
113
+ zip_path = os.path.join(temp_dir, zip_name)
114
+
115
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
116
+ for file_obj in files:
117
+ # Handle Gradio 6+ file object format
118
+ if isinstance(file_obj, dict):
119
+ file_path = file_obj["path"]
120
+ file_name = file_obj["name"]
121
+ else:
122
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
123
+ file_name = os.path.basename(file_path)
124
+
125
+ # Create individual zip first
126
+ base_name = os.path.splitext(file_name)[0]
127
+ individual_zip_name = f"{base_name}.zip"
128
+ individual_zip_path = os.path.join(temp_dir, individual_zip_name)
129
+
130
+ with zipfile.ZipFile(individual_zip_path, 'w', zipfile.ZIP_DEFLATED) as ind_zip:
131
+ ind_zip.write(file_path, file_name)
132
+
133
+ # Add individual zip to main zip
134
+ zipf.write(individual_zip_path, individual_zip_name)
135
+
136
+ return zip_path, f"✅ Created zip with {len(files)} individual zips"
137
+
138
+ else:
139
+ return None, "❌ Invalid action selected"
140
+
141
+ except Exception as e:
142
+ return None, f"❌ Error: {str(e)}"
143
+
144
+ def get_file_info(file_obj):
145
+ """Get information about uploaded file"""
146
+ if not file_obj:
147
+ return "No file selected"
148
+
149
+ try:
150
+ # Handle Gradio 6+ file object format
151
+ if isinstance(file_obj, dict):
152
+ file_path = file_obj["path"]
153
+ file_name = file_obj["name"]
154
+ else:
155
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
156
+ file_name = os.path.basename(file_path)
157
+
158
+ file_size = os.path.getsize(file_path)
159
+ file_ext = os.path.splitext(file_name)[1].lower()
160
+
161
+ # Get file type
162
+ mime_type, _ = mimetypes.guess_type(file_path)
163
+ file_type = mime_type.split('/')[0] if mime_type else "Unknown"
164
+
165
+ # Get creation and modification times
166
+ ctime = time.ctime(os.path.getctime(file_path))
167
+ mtime = time.ctime(os.path.getmtime(file_path))
168
+
169
+ info = f"""
170
+ 📄 **File Information:**
171
+
172
+ **Name:** {file_name}
173
+ **Size:** {file_size:,} bytes ({file_size/1024:.2f} KB)
174
+ **Extension:** {file_ext}
175
+ **Type:** {file_type}
176
+ **Created:** {ctime}
177
+ **Modified:** {mtime}
178
+ **Path:** {file_path}
179
+ """
180
+
181
+ return info
182
+
183
+ except Exception as e:
184
+ return f"❌ Error getting file info: {str(e)}"
185
+
186
+ # Create Gradio interface
187
+ with gr.Blocks(title="File Upload & Download Manager", theme=gr.themes.Soft()) as iface:
188
+
189
+ gr.Markdown("# 📁 File Upload & Download Manager")
190
+ gr.Markdown("Upload files and download them as original or zipped")
191
+
192
+ with gr.Tabs():
193
+ # Single File Tab
194
+ with gr.Tab("Single File"):
195
+ with gr.Row():
196
+ with gr.Column(scale=2):
197
+ single_file = gr.File(
198
+ label="Upload a File",
199
+ file_count="single"
200
+ )
201
+
202
+ file_name_input = gr.Textbox(
203
+ label="Custom Filename (optional)",
204
+ placeholder="Leave empty to keep original name...",
205
+ info="Enter a custom name for the downloaded file"
206
+ )
207
+
208
+ single_action = gr.Radio(
209
+ choices=[
210
+ ("Download Original", "original"),
211
+ ("Download as ZIP", "zip"),
212
+ ("Password-protected ZIP", "zip_with_password")
213
+ ],
214
+ label="Select Action",
215
+ value="original"
216
+ )
217
+
218
+ single_btn = gr.Button("Process File", variant="primary")
219
+
220
+ with gr.Column(scale=1):
221
+ file_info = gr.Markdown(label="File Information")
222
+ single_status = gr.Textbox(label="Status", interactive=False)
223
+ single_download = gr.File(label="Download Processed File", interactive=False)
224
+
225
+ # Update file info when file is uploaded
226
+ single_file.change(
227
+ fn=get_file_info,
228
+ inputs=[single_file],
229
+ outputs=file_info
230
+ )
231
+
232
+ # Multiple Files Tab
233
+ with gr.Tab("Multiple Files"):
234
+ with gr.Row():
235
+ with gr.Column(scale=2):
236
+ multi_files = gr.File(
237
+ label="Upload Multiple Files",
238
+ file_count="multiple",
239
+ # Updated file_types format for Gradio 6+
240
+ file_types=[
241
+ "image", "video", "audio",
242
+ "text", ".pdf", ".zip", ".txt",
243
+ ".doc", ".docx", ".xls", ".xlsx"
244
+ ]
245
+ )
246
+
247
+ multi_action = gr.Radio(
248
+ choices=[
249
+ ("Combine all files into one ZIP", "individual"),
250
+ ("Create separate ZIPs for each file", "separate")
251
+ ],
252
+ label="Select Action",
253
+ value="individual"
254
+ )
255
+
256
+ multi_btn = gr.Button("Process Files", variant="primary")
257
+
258
+ with gr.Column(scale=1):
259
+ multi_status = gr.Textbox(label="Status", interactive=False)
260
+ multi_download = gr.File(label="Download Processed Files", interactive=False)
261
+
262
+ # Batch Processing Tab
263
+ with gr.Tab("Batch Processing"):
264
+ with gr.Row():
265
+ with gr.Column():
266
+ gr.Markdown("### Upload Multiple Files for Batch Processing")
267
+
268
+ batch_files = gr.File(
269
+ label="Upload Files",
270
+ file_count="multiple",
271
+ file_types=None # All file types
272
+ )
273
+
274
+ batch_options = gr.CheckboxGroup(
275
+ choices=[
276
+ "Create individual ZIPs",
277
+ "Create combined ZIP",
278
+ "Rename with timestamp",
279
+ "Add to existing ZIP"
280
+ ],
281
+ label="Processing Options",
282
+ value=["Create combined ZIP"]
283
+ )
284
+
285
+ with gr.Row():
286
+ batch_format = gr.Dropdown(
287
+ choices=[".zip", ".7z", ".tar.gz"],
288
+ value=".zip",
289
+ label="Archive Format"
290
+ )
291
+
292
+ compression_level = gr.Slider(
293
+ minimum=1,
294
+ maximum=9,
295
+ value=6,
296
+ step=1,
297
+ label="Compression Level"
298
+ )
299
+
300
+ batch_btn = gr.Button("Process Batch", variant="primary", size="lg")
301
+
302
+ with gr.Column():
303
+ batch_status = gr.Textbox(label="Status", interactive=False, lines=3)
304
+ batch_download = gr.File(label="Download Results", interactive=False)
305
+
306
+ # Instructions
307
+ with gr.Accordion("📖 Instructions & Features", open=False):
308
+ gr.Markdown("""
309
+ ## How to Use:
310
+
311
+ ### Single File Tab:
312
+ 1. **Upload** a single file
313
+ 2. (Optional) Enter a custom filename
314
+ 3. **Choose action**: Download original, as ZIP, or password-protected ZIP
315
+ 4. Click **Process File**
316
+
317
+ ### Multiple Files Tab:
318
+ 1. **Upload** multiple files (Ctrl+Click to select multiple)
319
+ 2. **Choose action**: Combine into one ZIP or create separate ZIPs
320
+ 3. Click **Process Files**
321
+
322
+ ### Batch Processing Tab:
323
+ 1. **Upload** multiple files
324
+ 2. **Select processing options**
325
+ 3. Choose archive format and compression level
326
+ 4. Click **Process Batch**
327
+
328
+ ## Features:
329
+ - ✅ Single file upload and download
330
+ - ✅ Multiple file upload and batch processing
331
+ - ✅ ZIP file creation with compression
332
+ - ✅ Password-protected ZIPs (requires pyminizip)
333
+ - ✅ File information display
334
+ - ✅ Custom filename support
335
+ - ✅ Multiple archive formats
336
+
337
+ ## Notes:
338
+ - Files are processed in temporary storage
339
+ - Original files are not modified
340
+ - Large files may take time to process
341
+ - Password for protected ZIPs: `password123`
342
+ - For Gradio 6+ compatibility, file objects are handled differently
343
+ """)
344
+
345
+ # Connect events
346
+ single_btn.click(
347
+ fn=process_file,
348
+ inputs=[single_file, file_name_input, single_action],
349
+ outputs=[single_download, single_status]
350
+ )
351
+
352
+ multi_btn.click(
353
+ fn=process_multiple_files,
354
+ inputs=[multi_files, multi_action],
355
+ outputs=[multi_download, multi_status]
356
+ )
357
+
358
+ # Batch processing function
359
+ def process_batch(files, options, format_type, compression):
360
+ if not files:
361
+ return None, "❌ No files uploaded"
362
+
363
+ try:
364
+ temp_dir = tempfile.mkdtemp()
365
+ results = []
366
+
367
+ # Process based on options
368
+ if "Create combined ZIP" in options:
369
+ zip_name = f"combined{format_type}"
370
+ zip_path = os.path.join(temp_dir, zip_name)
371
+
372
+ if format_type == ".zip":
373
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression) as zipf:
374
+ for file_obj in files:
375
+ # Handle Gradio 6+ file object format
376
+ if isinstance(file_obj, dict):
377
+ file_path = file_obj["path"]
378
+ arcname = file_obj["name"]
379
+ else:
380
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
381
+ arcname = os.path.basename(file_path)
382
+
383
+ if "Rename with timestamp" in options:
384
+ name, ext = os.path.splitext(arcname)
385
+ arcname = f"{name}_{int(time.time())}{ext}"
386
+ zipf.write(file_path, arcname)
387
+
388
+ results.append(zip_path)
389
+
390
+ if "Create individual ZIPs" in options:
391
+ for file_obj in files:
392
+ # Handle Gradio 6+ file object format
393
+ if isinstance(file_obj, dict):
394
+ file_path = file_obj["path"]
395
+ file_name = file_obj["name"]
396
+ else:
397
+ file_path = file_obj.name if hasattr(file_obj, 'name') else file_obj
398
+ file_name = os.path.basename(file_path)
399
+
400
+ base_name = os.path.splitext(file_name)[0]
401
+ if "Rename with timestamp" in options:
402
+ base_name = f"{base_name}_{int(time.time())}"
403
+
404
+ individual_zip_name = f"{base_name}{format_type}"
405
+ individual_zip_path = os.path.join(temp_dir, individual_zip_name)
406
+
407
+ if format_type == ".zip":
408
+ with zipfile.ZipFile(individual_zip_path, 'w', zipfile.ZIP_DEFLATED, compresslevel=compression) as zipf:
409
+ zipf.write(file_path, file_name)
410
+
411
+ results.append(individual_zip_path)
412
+
413
+ # If multiple results, create a final zip
414
+ if len(results) > 1:
415
+ final_zip_name = f"batch_results{format_type}"
416
+ final_zip_path = os.path.join(temp_dir, final_zip_name)
417
+
418
+ with zipfile.ZipFile(final_zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
419
+ for result_path in results:
420
+ zipf.write(result_path, os.path.basename(result_path))
421
+
422
+ output_file = final_zip_path
423
+ elif results:
424
+ output_file = results[0]
425
+ else:
426
+ return None, "⚠️ No processing options selected"
427
+
428
+ return output_file, f"✅ Processed {len(files)} file(s) with {len(options)} option(s)"
429
+
430
+ except Exception as e:
431
+ return None, f"❌ Error: {str(e)}"
432
+
433
+ batch_btn.click(
434
+ fn=process_batch,
435
+ inputs=[batch_files, batch_options, batch_format, compression_level],
436
+ outputs=[batch_download, batch_status]
437
+ )
438
+
439
+ # Launch the app - SIMPLIFIED FOR HUGGING FACE SPACES
440
+ if __name__ == "__main__":
441
+ # For Hugging Face Spaces, use simple launch without port specification
442
+ iface.launch(
443
+ show_error=True,
444
+ share=False,
445
+ theme=gr.themes.Soft()
446
+ )