Files
MapAssignFlag/server.py
user01 9cf163908f Store photos on server, save path in Excel instead of base64
- Add POST /upload endpoint to server.py (saves to photos/ dir)
- Add DELETE /photos/ endpoint for photo removal
- Replace base64 photoData with server-stored photoPath
- Export/import uses path string instead of large base64 data
2026-05-15 19:08:21 +09:00

85 lines
3.1 KiB
Python

import http.server
import socketserver
import os
import urllib.parse
import uuid
PORT = 8000
PHOTO_DIR = 'photos'
os.makedirs(PHOTO_DIR, exist_ok=True)
class Handler(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
if self.path == '/upload':
content_len = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_len)
# parse multipart/form-data
boundary = self.headers.get('Content-Type', '').split('boundary=')[-1].encode()
if not boundary:
self.send_error(400, 'Missing boundary')
return
parts = body.split(b'--' + boundary)
filename = None
file_data = None
for part in parts:
if b'Content-Disposition' in part:
header_end = part.find(b'\r\n\r\n')
if header_end == -1:
continue
header_section = part[:header_end].decode('utf-8', errors='replace')
data = part[header_end + 4:]
data = data.rstrip(b'\r\n--')
# Check if this part has a filename
for line in header_section.split('\r\n'):
if 'filename="' in line:
orig_name = line.split('filename="')[1].split('"')[0]
ext = os.path.splitext(orig_name)[1] or '.jpg'
fname = uuid.uuid4().hex + ext
file_data = data
filename = fname
break
if filename and file_data:
path = os.path.join(PHOTO_DIR, filename)
with open(path, 'wb') as f:
f.write(file_data)
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.end_headers()
self.wfile.write(('{"path":"photos/' + filename + '"}').encode())
else:
self.send_error(400, 'No file found')
else:
self.send_error(404)
def do_DELETE(self):
parsed = urllib.parse.urlparse(self.path)
if parsed.path.startswith('/photos/'):
rel = os.path.relpath(parsed.path, '/photos/')
# basic path safety
if '..' in rel or rel.startswith('/'):
self.send_error(400)
return
filepath = os.path.join(PHOTO_DIR, rel)
if os.path.exists(filepath):
os.remove(filepath)
self.send_response(200)
self.end_headers()
self.wfile.write(b'{"ok":true}')
else:
self.send_error(404)
else:
self.send_error(404)
def log_message(self, format, *args):
if '/upload' in str(args[0]) or '/photos/' in str(args[0]):
return # skip noisy upload logs
super().log_message(format, *args)
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print(f"Serving at http://0.0.0.0:{PORT}")
httpd.serve_forever()