77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
"""Admin media library API - list & upload images (session-authenticated)."""
|
|
import os
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
from fastapi import APIRouter, HTTPException, Request, UploadFile
|
|
from fastapi.responses import JSONResponse
|
|
|
|
from app.core.config import settings
|
|
|
|
router = APIRouter(prefix="/admin/api/media", tags=["admin-media"])
|
|
|
|
ALLOWED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".gif", ".webp"}
|
|
MAX_SIZE = 10 * 1024 * 1024
|
|
|
|
|
|
def _check_admin_session(request: Request):
|
|
uid = request.session.get("admin_user_id")
|
|
if not uid:
|
|
raise HTTPException(status_code=401, detail="未登录")
|
|
|
|
|
|
@router.get("/list")
|
|
async def list_media(request: Request):
|
|
_check_admin_session(request)
|
|
|
|
images = []
|
|
|
|
if settings.STORAGE_BACKEND == "local":
|
|
upload_dir = Path(settings.LOCAL_STORAGE_PATH)
|
|
if upload_dir.exists():
|
|
for f in sorted(upload_dir.iterdir(), key=lambda p: p.stat().st_mtime, reverse=True):
|
|
if f.is_file() and f.suffix.lower() in ALLOWED_EXTENSIONS:
|
|
images.append({
|
|
"url": f"/uploads/{f.name}",
|
|
"name": f.name,
|
|
"size": f.stat().st_size,
|
|
})
|
|
else:
|
|
storage = request.app.state.storage
|
|
try:
|
|
resp = storage.client.list_objects_v2(Bucket=storage.bucket, Prefix="images/", MaxKeys=200)
|
|
for obj in resp.get("Contents", []):
|
|
key = obj["Key"]
|
|
ext = Path(key).suffix.lower()
|
|
if ext in ALLOWED_EXTENSIONS:
|
|
images.append({
|
|
"url": storage._get_url(key),
|
|
"name": Path(key).name,
|
|
"size": obj.get("Size", 0),
|
|
})
|
|
except Exception:
|
|
pass
|
|
|
|
return JSONResponse({"images": images})
|
|
|
|
|
|
@router.post("/upload")
|
|
async def upload_media(request: Request, file: UploadFile):
|
|
_check_admin_session(request)
|
|
|
|
if not file.filename:
|
|
raise HTTPException(status_code=400, detail="缺少文件")
|
|
|
|
ext = Path(file.filename).suffix.lower()
|
|
if ext not in ALLOWED_EXTENSIONS:
|
|
raise HTTPException(status_code=400, detail=f"不支持的文件类型: {ext}")
|
|
|
|
data = await file.read()
|
|
if len(data) > MAX_SIZE:
|
|
raise HTTPException(status_code=413, detail="文件过大,最大10MB")
|
|
|
|
storage = request.app.state.storage
|
|
url = storage.upload(data, file.filename, file.content_type or "")
|
|
|
|
return JSONResponse({"url": url, "name": file.filename})
|