Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from PIL import Image
|
| 3 |
+
import os, time, uuid
|
| 4 |
+
|
| 5 |
+
# If your Space has "Persistent Storage" enabled, /data is the mount point.
|
| 6 |
+
# If not, it still works but files won't survive a restart.
|
| 7 |
+
SAVE_DIR = os.getenv("SAVE_DIR", "/data/uploads")
|
| 8 |
+
os.makedirs(SAVE_DIR, exist_ok=True)
|
| 9 |
+
|
| 10 |
+
ALLOWED_FORMATS = {"JPEG", "PNG"} # strict enforcement
|
| 11 |
+
|
| 12 |
+
def handle_upload(file_path: str):
|
| 13 |
+
if not file_path:
|
| 14 |
+
return "Please choose an image.", None
|
| 15 |
+
|
| 16 |
+
# Verify the real file type by reading the header via Pillow.
|
| 17 |
+
try:
|
| 18 |
+
with Image.open(file_path) as im:
|
| 19 |
+
fmt = (im.format or "").upper()
|
| 20 |
+
if fmt not in ALLOWED_FORMATS:
|
| 21 |
+
return f"Only JPEG/PNG allowed. Detected: {fmt or 'unknown'}.", None
|
| 22 |
+
|
| 23 |
+
# Optional: normalize mode (e.g., ensure RGB)
|
| 24 |
+
if im.mode not in ("RGB", "RGBA"):
|
| 25 |
+
im = im.convert("RGB")
|
| 26 |
+
|
| 27 |
+
# Save with a unique filename
|
| 28 |
+
ext = ".jpg" if fmt == "JPEG" else ".png"
|
| 29 |
+
filename = f"{int(time.time())}_{uuid.uuid4().hex}{ext}"
|
| 30 |
+
save_path = os.path.join(SAVE_DIR, filename)
|
| 31 |
+
im.save(save_path)
|
| 32 |
+
|
| 33 |
+
info = f"✅ Saved as **{filename}** · {im.width}×{im.height}px · {fmt}"
|
| 34 |
+
# Return a copy for the preview (so file handle is closed)
|
| 35 |
+
return info, im.copy()
|
| 36 |
+
except Exception as e:
|
| 37 |
+
return f"Failed to read image: {e}", None
|
| 38 |
+
|
| 39 |
+
with gr.Blocks(title="Image Upload (JPEG/PNG)") as demo:
|
| 40 |
+
gr.Markdown("### Upload an image (JPEG/PNG). It will be validated and saved to storage.")
|
| 41 |
+
with gr.Row():
|
| 42 |
+
inp = gr.Image(
|
| 43 |
+
label="Drop or click to upload",
|
| 44 |
+
type="filepath", # gives us the original temp filepath
|
| 45 |
+
image_mode="RGB",
|
| 46 |
+
sources=["upload", "clipboard"]
|
| 47 |
+
)
|
| 48 |
+
preview = gr.Image(label="Preview", interactive=False)
|
| 49 |
+
|
| 50 |
+
msg = gr.Markdown()
|
| 51 |
+
# Auto-save on change; also provide an explicit button for clarity.
|
| 52 |
+
inp.change(handle_upload, inputs=inp, outputs=[msg, preview])
|
| 53 |
+
gr.Button("Save").click(handle_upload, inputs=inp, outputs=[msg, preview])
|
| 54 |
+
|
| 55 |
+
if __name__ == "__main__":
|
| 56 |
+
demo.launch()
|