224 lines
No EOL
6.2 KiB
Python
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
|
|
} |