199 lines
7.7 KiB
Python
199 lines
7.7 KiB
Python
# _*_ coding : UTF-8 _*_
|
|
# @Time : 2025/01/25 22:16
|
|
# @UpdateTime : 2025/01/25 22:16
|
|
# @Author : sonder
|
|
# @File : file.py
|
|
# @Software : PyCharm
|
|
# @Comment : 本程序
|
|
import os
|
|
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, UploadFile, File, Path, Depends, Request, Query
|
|
from fastapi.responses import FileResponse, JSONResponse
|
|
|
|
from annotation.log import Log
|
|
from config.constant import BusinessType
|
|
from config.env import UploadConfig
|
|
from controller.login import LoginController
|
|
from exceptions.exception import ModelValidatorException, ServiceException
|
|
from models import File as FileModel
|
|
from schemas.common import BaseResponse
|
|
from schemas.file import UploadFileResponse, GetFileInfoResponse, GetFileListResponse
|
|
from utils.response import Response
|
|
from utils.upload import Upload
|
|
|
|
fileAPI = APIRouter(
|
|
prefix="/file",
|
|
)
|
|
|
|
|
|
@fileAPI.post("/upload", response_model=UploadFileResponse, response_class=JSONResponse, summary="上传文件")
|
|
@Log(title="上传文件", business_type=BusinessType.INSERT)
|
|
async def upload_file(
|
|
request: Request,
|
|
file: UploadFile = File(..., description="上传的文件"),
|
|
current_user: dict = Depends(LoginController.get_current_user),
|
|
):
|
|
# 1. 检查文件扩展名是否允许
|
|
file_extension = os.path.splitext(file.filename)[1][1:].lower() # 获取文件扩展名并转换为小写
|
|
if file_extension not in UploadConfig.DEFAULT_ALLOWED_EXTENSION:
|
|
raise ModelValidatorException(message="文件类型不支持")
|
|
|
|
# 2. 生成唯一的文件名
|
|
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
|
|
unique_filename = f"{current_user.get('id')}_{timestamp}.{file_extension}"
|
|
|
|
# 3. 保存文件到服务器
|
|
file_path = os.path.join(UploadConfig.UPLOAD_PATH, unique_filename)
|
|
with open(file_path, "wb") as buffer:
|
|
buffer.write(await file.read())
|
|
|
|
# 4. 构建文件的相对路径和绝对路径
|
|
relative_path = os.path.join(UploadConfig.UPLOAD_PREFIX, unique_filename) # 相对路径
|
|
absolute_path = os.path.abspath(file_path) # 绝对路径
|
|
|
|
# 5. 将文件信息保存到数据库
|
|
file_record = await FileModel.create(
|
|
name=file.filename,
|
|
size=os.path.getsize(file_path),
|
|
file_type=file.content_type,
|
|
absolute_path=absolute_path,
|
|
relative_path=relative_path,
|
|
uploader=current_user.get("id"),
|
|
)
|
|
result = await file_record.first().values(
|
|
id="id",
|
|
name="name",
|
|
size="size",
|
|
file_type="file_type",
|
|
relative_path="relative_path",
|
|
absolute_path="absolute_path",
|
|
uploader_id="uploader__id",
|
|
uploader_username="uploader__username",
|
|
uploader_nickname="uploader__nickname",
|
|
uploader_department_id="uploader__department__id",
|
|
uploader_department_name="uploader__department__name",
|
|
create_time="create_time",
|
|
update_time="update_time",
|
|
)
|
|
return Response.success(data=result)
|
|
|
|
|
|
@fileAPI.get("/{id}", summary="下载文件")
|
|
@Log(title="获取文件", business_type=BusinessType.SELECT)
|
|
async def download_file(
|
|
request: Request,
|
|
id: str = Path(..., description="文件ID"),
|
|
):
|
|
# 1. 查询文件记录
|
|
file_record = await FileModel.get_or_none(id=id)
|
|
if not file_record:
|
|
raise ServiceException(message="文件不存在!")
|
|
|
|
# 2. 检查文件是否存在
|
|
if not os.path.exists(file_record.absolute_path):
|
|
raise ServiceException(message="文件不存在!")
|
|
|
|
# 3. 返回文件内容
|
|
return FileResponse(
|
|
path=file_record.absolute_path,
|
|
filename=file_record.name,
|
|
media_type=file_record.file_type,
|
|
)
|
|
|
|
|
|
@fileAPI.get("/info/{id}", response_class=JSONResponse, response_model=GetFileInfoResponse, summary="获取文件信息")
|
|
@Log(title="获取文件信息", business_type=BusinessType.SELECT)
|
|
async def get_file_info(
|
|
request: Request,
|
|
id: str = Path(..., description="文件ID"),
|
|
current_user: dict = Depends(LoginController.get_current_user),
|
|
):
|
|
# 1. 查询文件记录
|
|
file_record = await FileModel.get_or_none(id=id)
|
|
if not file_record:
|
|
raise ServiceException(message="文件不存在!")
|
|
result = await file_record.first().values(
|
|
id="id",
|
|
name="name",
|
|
size="size",
|
|
file_type="file_type",
|
|
relative_path="relative_path",
|
|
absolute_path="absolute_path",
|
|
uploader_id="uploader__id",
|
|
uploader_username="uploader__username",
|
|
uploader_nickname="uploader__nickname",
|
|
uploader_department_id="uploader__department__id",
|
|
uploader_department_name="uploader__department__name",
|
|
create_time="create_time",
|
|
update_time="update_time",
|
|
)
|
|
return Response.success(data=result)
|
|
|
|
|
|
@fileAPI.delete("/delete/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除文件")
|
|
@fileAPI.post("/delete/{id}", response_class=JSONResponse, response_model=BaseResponse, summary="删除文件")
|
|
@Log(title="删除文件", business_type=BusinessType.DELETE)
|
|
async def delete_file(
|
|
request: Request,
|
|
id: str = Path(..., description="文件ID"),
|
|
current_user: dict = Depends(LoginController.get_current_user), ):
|
|
# 1. 查询文件记录
|
|
file_record = await FileModel.get_or_none(id=id)
|
|
if not file_record:
|
|
raise ServiceException(message="文件不存在!")
|
|
if await Upload.check_file_exists(file_record.absolute_path):
|
|
await Upload.delete_file(file_record.absolute_path)
|
|
await file_record.delete()
|
|
return Response.success()
|
|
|
|
|
|
@fileAPI.get("/list", response_class=JSONResponse, response_model=GetFileListResponse, summary="获取文件列表")
|
|
@Log(title="获取文件列表", business_type=BusinessType.SELECT)
|
|
async def get_file_list(
|
|
request: Request,
|
|
page: int = Query(default=1, description="页码"),
|
|
pageSize: int = Query(default=10, description="每页数量"),
|
|
name: str = Query(default=None, description="文件名"),
|
|
file_type: str = Query(default=None, description="文件类型"),
|
|
uploader_id: str = Query(default=None, description="上传者ID"),
|
|
uploader_username: str = Query(default=None, description="上传者用户名"),
|
|
uploader_nickname: str = Query(default=None, description="上传者昵称"),
|
|
department_id: str = Query(default=None, description="上传者部门ID"),
|
|
department_name: str = Query(default=None, description="上传者部门名称"),
|
|
current_user: dict = Depends(LoginController.get_current_user), ):
|
|
# 1. 查询文件记录
|
|
filterArgs = {
|
|
f'{k}__contains': v for k, v in {
|
|
'name': name,
|
|
'file_type': file_type,
|
|
'uploader__id': uploader_id,
|
|
'uploader__username': uploader_username,
|
|
'uploader__nickname': uploader_nickname,
|
|
'uploader__department__id': department_id,
|
|
'uploader__department__name': department_name
|
|
}.items() if v
|
|
}
|
|
total = await FileModel.filter(**filterArgs).count()
|
|
result = await FileModel.filter(**filterArgs).order_by('-create_time').offset((page - 1) * pageSize).limit(
|
|
pageSize).values(
|
|
id="id",
|
|
name="name",
|
|
size="size",
|
|
file_type="file_type",
|
|
relative_path="relative_path",
|
|
absolute_path="absolute_path",
|
|
uploader_id="uploader__id",
|
|
uploader_username="uploader__username",
|
|
uploader_nickname="uploader__nickname",
|
|
uploader_department_id="uploader__department__id",
|
|
uploader_department_name="uploader__department__name",
|
|
create_time="create_time",
|
|
update_time="update_time",
|
|
)
|
|
return Response.success(data={
|
|
"total": total,
|
|
"result": result,
|
|
"page": page,
|
|
})
|