RojaKatta commited on
Commit
a0e0dac
·
verified ·
1 Parent(s): 3c5d9dd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -17
app.py CHANGED
@@ -1,56 +1,100 @@
 
 
 
 
 
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()
 
 
1
+ import os
2
+ import time
3
+ import uuid
4
+ from typing import Optional
5
+
6
  import gradio as gr
7
  from PIL import Image
 
8
 
9
+ # ------------------------------------------------------------
10
+ # Pick a writable save directory automatically.
11
+ # Order:
12
+ # 1) SAVE_DIR env var (if supplied)
13
+ # 2) /data/uploads (when Persistent Storage is enabled)
14
+ # 3) /home/user/app/uploads (always writable in Spaces)
15
+ # 4) /tmp/uploads (always writable, ephemeral)
16
+ # ------------------------------------------------------------
17
+ def pick_writable_dir() -> str:
18
+ candidates = []
19
+ env_dir = os.getenv("SAVE_DIR")
20
+ if env_dir:
21
+ candidates.append(env_dir)
22
+ candidates += ["/data/uploads", "/home/user/app/uploads", "/tmp/uploads"]
23
+
24
+ for path in candidates:
25
+ try:
26
+ os.makedirs(path, exist_ok=True)
27
+ # double-check we can create files here
28
+ testfile = os.path.join(path, f".write_test_{uuid.uuid4().hex}")
29
+ with open(testfile, "w") as f:
30
+ f.write("ok")
31
+ os.remove(testfile)
32
+ return path
33
+ except Exception:
34
+ continue
35
+ # last resort: current directory
36
+ fallback = "./uploads"
37
+ os.makedirs(fallback, exist_ok=True)
38
+ return fallback
39
 
40
+ SAVE_DIR = pick_writable_dir()
41
 
42
+ ALLOWED_FORMATS = {"JPEG", "PNG"} # strict type enforcement
43
+
44
+ def handle_upload(file_path: Optional[str]):
45
  if not file_path:
46
  return "Please choose an image.", None
47
 
 
48
  try:
49
  with Image.open(file_path) as im:
50
  fmt = (im.format or "").upper()
51
  if fmt not in ALLOWED_FORMATS:
52
  return f"Only JPEG/PNG allowed. Detected: {fmt or 'unknown'}.", None
53
 
54
+ # Normalize to RGB so we can always save safely
55
  if im.mode not in ("RGB", "RGBA"):
56
  im = im.convert("RGB")
57
 
58
+ # Choose extension from the detected format
59
  ext = ".jpg" if fmt == "JPEG" else ".png"
60
  filename = f"{int(time.time())}_{uuid.uuid4().hex}{ext}"
61
  save_path = os.path.join(SAVE_DIR, filename)
 
62
 
63
+ # Reasonable defaults for each format
64
+ if fmt == "JPEG":
65
+ im.save(save_path, quality=90, optimize=True)
66
+ else:
67
+ im.save(save_path, optimize=True)
68
+
69
+ info = (
70
+ f"✅ Saved to **{save_path}**\n\n"
71
+ f"- File: **{filename}**\n"
72
+ f"- Size: **{im.width}×{im.height}px**\n"
73
+ f"- Format: **{fmt}**"
74
+ )
75
  return info, im.copy()
76
  except Exception as e:
77
+ return f"Failed to read/save image: {e}", None
78
 
79
  with gr.Blocks(title="Image Upload (JPEG/PNG)") as demo:
80
+ gr.Markdown("### Upload a JPEG or PNG. The file will be validated and saved.")
81
  with gr.Row():
82
  inp = gr.Image(
83
  label="Drop or click to upload",
84
+ type="filepath", # keep original temp filepath
85
  image_mode="RGB",
86
  sources=["upload", "clipboard"]
87
  )
88
  preview = gr.Image(label="Preview", interactive=False)
89
 
90
  msg = gr.Markdown()
91
+
92
+ # Auto-save when the image changes; also allow manual click.
93
  inp.change(handle_upload, inputs=inp, outputs=[msg, preview])
94
  gr.Button("Save").click(handle_upload, inputs=inp, outputs=[msg, preview])
95
 
96
+ gr.Markdown(f"**Save directory:** `{SAVE_DIR}`")
97
+
98
  if __name__ == "__main__":
99
  demo.launch()
100
+