90 lines
3.1 KiB
Python
90 lines
3.1 KiB
Python
"""
|
||
文件管理路由模块
|
||
|
||
提供文件上传令牌生成和附件保存接口,支持:
|
||
- 生成云存储上传令牌(用于客户端直传)
|
||
- 保存文件附件元数据到数据库
|
||
|
||
URL 前缀:/api/files
|
||
权限要求:已登录用户(get_current_user)
|
||
"""
|
||
|
||
from datetime import datetime
|
||
from pathlib import Path
|
||
|
||
from fastapi import APIRouter, Depends, UploadFile
|
||
from sqlalchemy.orm import Session
|
||
|
||
from backend.app.api.deps import get_current_user
|
||
from backend.app.db import get_db_session
|
||
from backend.app.schemas.common import success_payload
|
||
from backend.app.schemas.files import CreateUploadTokenRequest, SaveAttachmentRequest
|
||
from backend.app.services.file_service import file_service
|
||
|
||
router = APIRouter(prefix="/api/files", tags=["files"])
|
||
|
||
|
||
@router.post("/upload-token")
|
||
def create_upload_token(
|
||
payload: CreateUploadTokenRequest, # 上传令牌请求体,包含文件名、类型等信息
|
||
session: Session = Depends(get_db_session), # 数据库会话
|
||
current_user: dict = Depends(get_current_user), # 当前登录用户
|
||
) -> dict:
|
||
"""
|
||
生成文件上传令牌
|
||
|
||
为客户端生成云存储的上传凭证,客户端可使用该令牌直接上传文件到云存储。
|
||
|
||
请求参数:
|
||
payload: CreateUploadTokenRequest 请求体,包含文件名、MIME类型等信息
|
||
|
||
返回值:
|
||
包含上传令牌、上传地址等信息的字典
|
||
"""
|
||
return success_payload(file_service.create_upload_token(payload.model_dump(), session))
|
||
|
||
|
||
@router.post("/attachments")
|
||
def save_attachment(
|
||
payload: SaveAttachmentRequest, # 保存附件请求体,包含文件URL、名称、大小等元数据
|
||
session: Session = Depends(get_db_session), # 数据库会话
|
||
current_user: dict = Depends(get_current_user), # 当前登录用户,用于记录创建人
|
||
) -> dict:
|
||
"""
|
||
保存文件附件元数据
|
||
|
||
文件上传至云存储后,调用此接口将附件的元数据(URL、文件名、大小等)保存到数据库,
|
||
并自动关联到当前登录用户作为创建人。
|
||
|
||
请求参数:
|
||
payload: SaveAttachmentRequest 请求体,包含文件元数据
|
||
|
||
返回值:
|
||
已保存的附件记录信息
|
||
|
||
权限要求:已登录用户
|
||
"""
|
||
return success_payload(file_service.save_attachment({**payload.model_dump(), "created_by": current_user.get("user_id")}, session))
|
||
|
||
|
||
LOCAL_UPLOAD_DIR = Path("D:/tmp/order-flow-oss/local-uploads")
|
||
|
||
|
||
@router.post("/local-upload")
|
||
async def local_upload(
|
||
file: UploadFile,
|
||
current_user: dict = Depends(get_current_user),
|
||
) -> dict:
|
||
"""开发环境本地文件上传,保存到本地目录并返回访问 URL。
|
||
|
||
绕过 OSS 直传,适用于本地开发调试场景。
|
||
"""
|
||
LOCAL_UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
|
||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
||
safe_name = Path(file.filename or "upload").name
|
||
file_path = LOCAL_UPLOAD_DIR / f"{timestamp}_{safe_name}"
|
||
content = await file.read()
|
||
file_path.write_bytes(content)
|
||
url = f"http://127.0.0.1:8000/uploads/{timestamp}_{safe_name}"
|
||
return success_payload({"url": url, "file_name": file.filename, "file_size": len(content)})
|