|
|
import gradio as gr |
|
|
import shutil |
|
|
import zipfile |
|
|
from datetime import datetime |
|
|
from pathlib import Path |
|
|
from PIL import Image |
|
|
import pillow_heif |
|
|
import tempfile |
|
|
import os |
|
|
|
|
|
|
|
|
BASE_DIR = Path(tempfile.gettempdir()) / "17eMIT" |
|
|
UPLOAD_FOLDER = BASE_DIR / "images" |
|
|
FILES_FOLDER = BASE_DIR / "files" |
|
|
UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True) |
|
|
FILES_FOLDER.mkdir(parents=True, exist_ok=True) |
|
|
|
|
|
|
|
|
IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.heic', '.webp', '.bmp', '.tiff'] |
|
|
FILE_EXTENSIONS = ['.mp3', '.m4a', '.mp4', '.pdf', '.docx', '.txt', '.xlsx', '.pptx'] |
|
|
|
|
|
def get_image_paths(limit=30): |
|
|
files = sorted(UPLOAD_FOLDER.glob("*"), key=lambda x: x.stat().st_mtime, reverse=True) |
|
|
return [str(f) for f in files if f.suffix.lower() in IMAGE_EXTENSIONS][:limit] |
|
|
|
|
|
def get_file_list(): |
|
|
files = sorted(FILES_FOLDER.glob("*"), key=lambda x: x.stat().st_mtime, reverse=True) |
|
|
return [f.name for f in files] |
|
|
|
|
|
def save_files(file_paths): |
|
|
if not file_paths: |
|
|
return "❗請選擇至少一個檔案", get_image_paths(), gr.update(choices=get_file_list()) |
|
|
|
|
|
messages = [] |
|
|
for file_path in file_paths: |
|
|
try: |
|
|
ext = Path(file_path).suffix.lower() |
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S%f") |
|
|
filename = f"{timestamp}{ext}" |
|
|
|
|
|
if ext in IMAGE_EXTENSIONS: |
|
|
if ext == ".heic": |
|
|
heif_file = pillow_heif.read_heif(file_path) |
|
|
image = Image.frombytes(heif_file.mode, heif_file.size, heif_file.data, "raw") |
|
|
else: |
|
|
image = Image.open(file_path).convert("RGB") |
|
|
|
|
|
filepath = UPLOAD_FOLDER / f"{timestamp}.png" |
|
|
image.save(filepath, format="PNG") |
|
|
elif ext in FILE_EXTENSIONS: |
|
|
filepath = FILES_FOLDER / filename |
|
|
shutil.copy(file_path, filepath) |
|
|
else: |
|
|
messages.append(f"❌ 不支援的檔案格式: {ext}") |
|
|
continue |
|
|
|
|
|
messages.append(f"✅ 檔案已上傳: {filename}") |
|
|
except Exception as e: |
|
|
messages.append(f"❌ 上傳失敗 ({file_path}): {str(e)}") |
|
|
|
|
|
return "\n".join(messages), get_image_paths(), gr.update(choices=get_file_list()) |
|
|
|
|
|
def clear_images(): |
|
|
try: |
|
|
shutil.rmtree(UPLOAD_FOLDER) |
|
|
shutil.rmtree(FILES_FOLDER) |
|
|
UPLOAD_FOLDER.mkdir(parents=True, exist_ok=True) |
|
|
FILES_FOLDER.mkdir(parents=True, exist_ok=True) |
|
|
return "🧹 所有圖片與檔案已清除", [], gr.update(choices=[]) |
|
|
except Exception as e: |
|
|
return f"❌ 清除失敗: {str(e)}", get_image_paths(), gr.update(choices=get_file_list()) |
|
|
|
|
|
def download_all_files(): |
|
|
all_files = list(UPLOAD_FOLDER.glob("*")) + list(FILES_FOLDER.glob("*")) |
|
|
if not all_files: |
|
|
return None, "⚠️ 沒有可下載的檔案" |
|
|
|
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
|
temp_zip = Path(tempfile.gettempdir()) / f"all_uploads_{timestamp}.zip" |
|
|
|
|
|
try: |
|
|
with zipfile.ZipFile(temp_zip, 'w', zipfile.ZIP_DEFLATED) as zipf: |
|
|
for filepath in all_files: |
|
|
zipf.write(filepath, arcname=filepath.name) |
|
|
return str(temp_zip), "✅ ZIP 文件已生成" |
|
|
except Exception as e: |
|
|
return None, f"❌ ZIP 文件生成失敗: {str(e)}" |
|
|
|
|
|
def cleanup_old_zips(): |
|
|
temp_dir = Path(tempfile.gettempdir()) |
|
|
for zip_file in temp_dir.glob("all_uploads_*.zip"): |
|
|
try: |
|
|
zip_file.unlink() |
|
|
except Exception: |
|
|
pass |
|
|
|
|
|
|
|
|
with gr.Blocks(title="📁 圖片與檔案分享平台") as demo: |
|
|
|
|
|
with gr.Row(): |
|
|
file_input = gr.File(label="上傳檔案", type="filepath", file_count="multiple") |
|
|
upload_button = gr.Button("📤 上傳", variant="primary") |
|
|
output_msg = gr.Textbox(label="狀態", lines=4, interactive=False) |
|
|
|
|
|
with gr.Row(): |
|
|
clear_button = gr.Button("🚫 清除所有", variant="stop") |
|
|
download_button = gr.Button("📦 下載全部", variant="primary") |
|
|
download_file = gr.File(label="點此下載 ZIP") |
|
|
zip_path_display = gr.Textbox(label="ZIP 文件訊息", lines=2, interactive=False) |
|
|
|
|
|
gr.Markdown("### 📄 上傳檔案列表") |
|
|
file_list = gr.Dropdown(label="所有檔案", choices=get_file_list(), interactive=False) |
|
|
|
|
|
gallery = gr.Gallery(label="📷 已上傳圖片", show_label=True, columns=3, object_fit="contain", height="500px") |
|
|
|
|
|
upload_button.click( |
|
|
fn=save_files, |
|
|
inputs=file_input, |
|
|
outputs=[output_msg, gallery, file_list] |
|
|
) |
|
|
|
|
|
clear_button.click( |
|
|
fn=clear_images, |
|
|
outputs=[output_msg, gallery, file_list] |
|
|
) |
|
|
|
|
|
download_button.click( |
|
|
fn=download_all_files, |
|
|
outputs=[download_file, zip_path_display] |
|
|
) |
|
|
|
|
|
demo.load(fn=get_image_paths, outputs=gallery) |
|
|
demo.load(fn=cleanup_old_zips) |
|
|
|
|
|
demo.launch() |
|
|
|