feat: 增加 /api/files/exists 与 /api/files/register-sftp 接口
- DAO 增加 get_by_sha256
- UploadService 抽出 _to_response 复用;新增 find_by_sha256、register_sftp
- 控制器新增两条路由(注意排在 /{file_id} 之前以避免被吞)
- 引入 SftpRegisterRequest schema
- SFTP 服务启动时自动创建 uploads/incoming/
- 行为:路径穿越 400、文件不存在 404、sha256 已存在则去重返回已有行
This commit is contained in:
@@ -10,7 +10,12 @@ from sqlalchemy.orm import Session
|
||||
|
||||
from ..database import get_db
|
||||
from ..dao.uploaded_file_dao import UploadedFileDAO
|
||||
from ..schemas.file import FileListResponse, FileUploadResponse, UploadedFileOut
|
||||
from ..schemas.file import (
|
||||
FileListResponse,
|
||||
FileUploadResponse,
|
||||
SftpRegisterRequest,
|
||||
UploadedFileOut,
|
||||
)
|
||||
from ..services.upload_service import UploadService
|
||||
|
||||
router = APIRouter(prefix="/api/files", tags=["files"])
|
||||
@@ -49,6 +54,42 @@ def list_files(
|
||||
return FileListResponse(total=total, items=items)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/exists",
|
||||
response_model=UploadedFileOut,
|
||||
summary="按 sha256 查询是否已上传",
|
||||
description="命中返回 200 + 元数据;未命中返回 404。供客户端在上传前去重。",
|
||||
)
|
||||
def file_exists(
|
||||
sha256: str,
|
||||
service: UploadService = Depends(_service),
|
||||
) -> UploadedFileOut:
|
||||
out = service.find_by_sha256(sha256)
|
||||
if out is None:
|
||||
raise HTTPException(404, "未找到匹配的 sha256")
|
||||
return out
|
||||
|
||||
|
||||
@router.post(
|
||||
"/register-sftp",
|
||||
response_model=FileUploadResponse,
|
||||
summary="登记一个已通过 SFTP 落盘的文件",
|
||||
description=(
|
||||
"客户端先把文件 SFTP 到 ``incoming/<name>``,再用本接口登记入库。"
|
||||
"服务端会计算 sha256(已存在则去重)、把文件原子改名到 ``YYYY/MM/<uuid>.<ext>``、写 DB 行。"
|
||||
),
|
||||
)
|
||||
def register_sftp(
|
||||
body: SftpRegisterRequest,
|
||||
service: UploadService = Depends(_service),
|
||||
) -> FileUploadResponse:
|
||||
return service.register_sftp(
|
||||
filename=body.filename,
|
||||
original_filename=body.original_filename,
|
||||
uploaded_by=body.uploaded_by,
|
||||
)
|
||||
|
||||
|
||||
@router.get("/{file_id}", response_model=UploadedFileOut, summary="查询单个文件元数据")
|
||||
def get_file(file_id: int, service: UploadService = Depends(_service)) -> UploadedFileOut:
|
||||
out = service.get_out(file_id)
|
||||
|
||||
Reference in New Issue
Block a user