Keep FastAPI as the only backend; add media upload, ntfy hook, and PB collection bootstrap for production. Co-authored-by: Cursor <cursoragent@cursor.com>
59 lines
1.5 KiB
Python
59 lines
1.5 KiB
Python
"""Media upload — FastAPI only, stored on S3 (SeaweedFS)."""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import APIRouter, File, Header, HTTPException, UploadFile
|
|
|
|
from app.services.auth import get_user_by_token
|
|
from app.services import s3_storage
|
|
from app.services.pb_client import pb
|
|
|
|
router = APIRouter(tags=["media"])
|
|
|
|
MAX_IMAGE = 10 * 1024 * 1024
|
|
MAX_VIDEO = 200 * 1024 * 1024
|
|
|
|
|
|
def _user(authorization: str | None) -> dict:
|
|
if not authorization or not authorization.startswith("Bearer "):
|
|
raise HTTPException(401, "未登录")
|
|
user = get_user_by_token(authorization[7:])
|
|
if not user:
|
|
raise HTTPException(401, "未登录")
|
|
return user
|
|
|
|
|
|
@router.post("/upload-media")
|
|
async def upload_media(
|
|
file: UploadFile = File(...),
|
|
purpose: str = "general",
|
|
authorization: str | None = Header(None),
|
|
):
|
|
user = _user(authorization)
|
|
ctype = (file.content_type or "").lower()
|
|
max_size = MAX_VIDEO if ctype.startswith("video/") else MAX_IMAGE
|
|
result = await s3_storage.upload_file(file, purpose=purpose, max_size=max_size)
|
|
|
|
if pb.health_ok():
|
|
try:
|
|
pb.create_record(
|
|
"media_assets",
|
|
{
|
|
"userId": user["id"],
|
|
"url": result.url,
|
|
"filename": file.filename or "",
|
|
"contentType": result.content_type,
|
|
"size": result.size,
|
|
"objectKey": result.object_key,
|
|
},
|
|
)
|
|
except Exception:
|
|
pass
|
|
|
|
return {
|
|
"success": True,
|
|
"url": result.url,
|
|
"object_key": result.object_key,
|
|
"size": result.size,
|
|
"content_type": result.content_type,
|
|
}
|