初始化

This commit is contained in:
zg
2026-07-15 16:08:17 +08:00
parent f0d70aded4
commit 4e0057ece5
89 changed files with 13512 additions and 0 deletions

101
backend/routes/upload.py Normal file
View File

@@ -0,0 +1,101 @@
"""文件上传/读取 — 数据库存储file_service.py 为可选备用方案,保留不删)"""
from fastapi import APIRouter, UploadFile, File, Depends, HTTPException, Request
from fastapi.responses import Response
from sqlalchemy.orm import Session
from logger import logger
from models import get_db, Upload
from middleware.user_context import UserContext
# 文件服务模块保留备用(不删除),如需切换取消下面注释即可
# from file_service import upload_file, download_file, delete_file
router = APIRouter(tags=["上传"])
ALLOWED = {"image/png", "image/jpeg", "image/gif", "image/webp", "image/svg+xml"}
MAX_SIZE = 20 * 1024 * 1024 # 20MB
@router.post("/api/upload/image")
async def upload_image(file: UploadFile = File(...), db: Session = Depends(get_db), request: Request = None):
"""上传图片 — 存入数据库 LONGBLOB"""
user_id = UserContext.get_user_id(request)
try:
if file.content_type not in ALLOWED:
raise HTTPException(400, f"不支持的图片格式: {file.content_type}")
data = await file.read()
if len(data) > MAX_SIZE:
raise HTTPException(400, f"图片不能超过 20MB当前 {len(data)} 字节")
filename = file.filename or "img"
logger.info(f"上传图片: {filename}, {len(data)} bytes, {file.content_type}, user={user_id}")
upload = Upload(
filename=filename,
content_type=file.content_type,
data=data,
size=len(data),
created_by=user_id,
)
db.add(upload)
db.commit()
db.refresh(upload)
logger.info(f"图片已存入 DB, id={upload.id}")
return {"url": f"/api/file/{upload.id}"}
except HTTPException:
raise
except Exception as e:
logger.error(f"上传失败: {e}")
raise HTTPException(500, f"上传失败: {str(e)}")
@router.get("/api/file/{file_id}")
def get_file(file_id: int, db: Session = Depends(get_db)):
"""读取图片 — 公开访问(不走网关,供编辑器 <img> 标签和分享页加载)
优先从 DB blob 读取;如为文件服务存储则代理下载
"""
upload = db.query(Upload).filter_by(id=file_id).first()
if not upload:
raise HTTPException(404, "文件不存在")
# DB blob主存储方式
if upload.data:
return Response(content=upload.data, media_type=upload.content_type)
# 文件服务存储(兼容之前上传的文件)
if upload.file_id:
from file_service import download_file
try:
data, content_type, _ = download_file(upload.file_id)
return Response(content=data, media_type=content_type)
except FileNotFoundError:
raise HTTPException(404, "文件在文件服务中不存在")
except Exception as e:
logger.error(f"从文件服务下载失败: {e}")
raise HTTPException(500, f"下载文件失败: {str(e)}")
raise HTTPException(404, "文件数据不存在")
@router.delete("/api/file/{file_id}")
def delete_file_api(file_id: int, db: Session = Depends(get_db), request: Request = None):
"""删除图片 — 从 DB 和文件服务中删除"""
user_id = UserContext.get_user_id(request)
upload = db.query(Upload).filter_by(id=file_id).first()
if not upload:
raise HTTPException(404, "文件不存在")
# 如果存在文件服务记录,同步删除
if upload.file_id:
from file_service import delete_file
try:
delete_file(upload.file_id)
logger.info(f"文件服务删除成功, fileId={upload.file_id}")
except Exception as e:
logger.error(f"文件服务删除失败: {e}")
db.delete(upload)
db.commit()
logger.info(f"图片记录已删除, db_id={file_id}, user={user_id}")
return {"ok": True}