chore: fork from IRIS track 供 LICA 部门独立运行
- 复制来源: /home/yueli/track @ 192c8ee (feature/ai-audit-update) - 组织隔离目标: LICA - 端口规划: 前端 8030 / 后端 8031 / 数据库 8032 - 已排除 deploy.sh、deploy_full.sh、docker-compose.prod.yml(IRIS 生产发布脚本) - 已排除工作区未提交改动,取干净的 192c8ee 状态
This commit is contained in:
51
backend/app/api/v1/endpoints/upload.py
Normal file
51
backend/app/api/v1/endpoints/upload.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""文件上传 & 静态文件访问"""
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from fastapi import APIRouter, UploadFile, File, HTTPException, status
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
router = APIRouter(prefix="/upload", tags=["文件上传"])
|
||||
|
||||
# Docker: os.getcwd() = /app → /app/uploads → host:backend/uploads
|
||||
BASE_DIR = os.environ.get("PROJECT_ROOT", os.getcwd())
|
||||
UPLOAD_DIR = os.path.join(BASE_DIR, "uploads")
|
||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||
|
||||
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif", "bmp", "webp", "pdf", "doc", "docx", "xls", "xlsx", "zip", "rar", "7z"}
|
||||
MAX_SIZE = 50 * 1024 * 1024 # 50MB
|
||||
|
||||
|
||||
@router.post("/")
|
||||
async def upload_file(file: UploadFile = File(...)) -> dict:
|
||||
"""上传文件 → 保存到 uploads/uuid.ext → 返回可访问 URL"""
|
||||
if not file.filename:
|
||||
raise HTTPException(status_code=400, detail="文件名为空")
|
||||
|
||||
ext = file.filename.rsplit(".", 1)[-1].lower() if "." in file.filename else ""
|
||||
if ext not in ALLOWED_EXTENSIONS:
|
||||
raise HTTPException(status_code=400, detail=f"不支持的文件类型: .{ext}")
|
||||
|
||||
# 检查大小
|
||||
content = await file.read()
|
||||
if len(content) > MAX_SIZE:
|
||||
raise HTTPException(status_code=400, detail="文件超过 50MB 限制")
|
||||
await file.seek(0)
|
||||
|
||||
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
||||
filename = f"{uuid.uuid4().hex}.{ext}"
|
||||
filepath = os.path.join(UPLOAD_DIR, filename)
|
||||
|
||||
with open(filepath, "wb") as f:
|
||||
f.write(await file.read())
|
||||
|
||||
return {"url": f"/api/v1/upload/files/{filename}"}
|
||||
|
||||
|
||||
@router.get("/files/{filename}")
|
||||
async def serve_file(filename: str):
|
||||
"""直接返回物理文件"""
|
||||
filepath = os.path.join(UPLOAD_DIR, filename)
|
||||
if not os.path.exists(filepath):
|
||||
raise HTTPException(status_code=404, detail="文件不存在")
|
||||
return FileResponse(filepath)
|
||||
Reference in New Issue
Block a user