from fastapi import FastAPI, UploadFile, File, HTTPException, Query from fastapi.responses import FileResponse from pathlib import Path from typing import Optional import shutil import uuid import os import httpx app = FastAPI() BASE_DIR = Path("/usr/src/app/taobin_project") # BASE_DIR = Path("/taobin_project") GIT_REPO_SERVER_URL = os.getenv("GIT_REPO_SERVER_URL") ALLOWED_FOLDERS = {"page_drink", "page_drink_disable", "page_drink_disable_n", "page_drink_disable_n2", "page_drink_n", "page_drink_picture2_n", "page_drink_press", "page_drink_press_n", "page_drink_select"} ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"} def validate_folder(folder: str): if folder not in ALLOWED_FOLDERS: raise HTTPException(400, f"folder must be {ALLOWED_FOLDERS}") def validate_ext(filename: str): ext = Path(filename).suffix.lower() if ext not in ALLOWED_EXTENSIONS: raise HTTPException(400, f"file not allow {ext}") return ext def get_image_dir(folder: str, country: Optional[str] = None) -> Path: """ no country → /taobin_project/image/{folder}/ has country → /taobin_project/inter/{country}/image/{folder}/ """ if country: path = BASE_DIR / "inter" / country / "image" / folder else: path = BASE_DIR / "image" / folder path.mkdir(parents=True, exist_ok=True) return path async def commit_files_to_git( files: list[UploadFile], folder: str, display_name: str, email: str, country: str, git_server_url: str = GIT_REPO_SERVER_URL ) -> dict: """ Commit file(s) to Git repository server via multipart form POST. Args: files: List of UploadFile objects (file pointers will be reset) folder: Folder name used in commit message display_name: Git signature username email: Git signature email git_server_url: Target Git repo server endpoint Returns: Response JSON from Git server """ commit_data = { "signature_username": display_name, "signature_email": email, "message": f"commit {folder} {country}" } multipart_files = {} if len(files) == 1: file_obj = files[0] file_obj.file.seek(0) commit_data["path"] = Path(file_obj.filename).name multipart_files["file"] = ( Path(file_obj.filename).name, file_obj.file, "application/octet-stream" ) else: for idx, file_obj in enumerate(files, start=1): file_obj.file.seek(0) commit_data[f"path{idx}"] = Path(file_obj.filename).name multipart_files[f"file{idx}"] = ( Path(file_obj.filename).name, file_obj.file, "application/octet-stream" ) # return { # "git_url": git_server_url, # "data": commit_data, # "file": multipart_files # } async with httpx.AsyncClient() as client: response = await client.post( git_server_url, data=commit_data, files=multipart_files, timeout=30.0 ) response.raise_for_status() return response.json() # ───────────────────────────────────────── # UPLOAD # ───────────────────────────────────────── @app.post("/image/{folder}/upload/{uid}/{displayname}/{email}") async def upload_images( folder: str, uid: str, displayname: str, email: str, files: list[UploadFile] = File(...) ): required_user_fields = { "uid": uid, "displayname": displayname, "email": email, "country": "tha" } if not (country): raise HTTPException(status_code=400, detail="Invalid country") for field, value in required_user_fields.items(): if not str(value).strip(): raise HTTPException( status_code=400, detail=f"Missing or empty user_info.{field}" ) validate_folder(folder) saved = [] for file in files: ext = validate_ext(file.filename) filename = Path(file.filename).name dest = get_image_dir(folder) / filename with open(dest, "wb") as f: shutil.copyfileobj(file.file, f) saved.append({ "filename": filename, "url": f"/image/{folder}/{filename}" }) # Commit to Git git_response = await commit_files_to_git( files=files, folder=folder, display_name=required_user_fields.get("displayname"), email=required_user_fields.get("email"), country=required_user_fields.get("country") ) return { "uploaded": saved, "git_commit": git_response } @app.post("/inter/{country}/image/{folder}/upload/{uid}/{displayname}/{email}") async def upload_inter_images( country: str, folder: str, uid: str, displayname: str, email: str, files: list[UploadFile] = File(...) ): required_user_fields = { "uid": uid, "displayname": displayname, "email": email, "country": country } if not (country): raise HTTPException(status_code=400, detail="Invalid country") for field, value in required_user_fields.items(): if not str(value).strip(): raise HTTPException( status_code=400, detail=f"Missing or empty user_info.{field}" ) validate_folder(folder) saved = [] for file in files: ext = validate_ext(file.filename) filename = Path(file.filename).name dest = get_image_dir(folder, country) / filename with open(dest, "wb") as f: shutil.copyfileobj(file.file, f) saved.append({ "filename": filename, "url": f"/inter/{country}/image/{folder}/{filename}" }) git_response = await commit_files_to_git( files=files, folder=folder, display_name=required_user_fields.get("displayname"), email=required_user_fields.get("email"), country=required_user_fields.get("country") ) return { "uploaded": saved, "git_commit": git_response }