taobin_image/main.py

224 lines
No EOL
6.2 KiB
Python

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
}