feat:单个文件的upload接口以及save接口
This commit is contained in:
@@ -0,0 +1,106 @@
|
|||||||
|
import asyncio
|
||||||
|
import os.path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from fastapi import FastAPI, UploadFile, Form
|
||||||
|
|
||||||
|
from app.config.env import env
|
||||||
|
from app.model.FileModel import FileSaveService
|
||||||
|
from app.utils.db_utils import AsyncSessionDep
|
||||||
|
from app.utils.path_join import path_join
|
||||||
|
|
||||||
|
|
||||||
|
def add_file_route(app: FastAPI):
|
||||||
|
async def _save_file(
|
||||||
|
session: AsyncSessionDep,
|
||||||
|
file: UploadFile,
|
||||||
|
body: dict,
|
||||||
|
):
|
||||||
|
filename = file.filename
|
||||||
|
return await FileSaveService.saveFile(
|
||||||
|
session=session,
|
||||||
|
file=file,
|
||||||
|
filename=filename,
|
||||||
|
id=body.get('id', None),
|
||||||
|
file_record=body,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def _save_file_list(
|
||||||
|
session: AsyncSessionDep,
|
||||||
|
file_list: List[UploadFile],
|
||||||
|
body: dict,
|
||||||
|
):
|
||||||
|
async_task_list = [asyncio.create_task(
|
||||||
|
FileSaveService.saveFile(
|
||||||
|
session=session,
|
||||||
|
file=item,
|
||||||
|
filename=item.filename,
|
||||||
|
file_record=body,
|
||||||
|
)
|
||||||
|
) for item in file_list]
|
||||||
|
result_list = await asyncio.gather(*async_task_list)
|
||||||
|
return {"result": result_list}
|
||||||
|
|
||||||
|
async def _delete_file(row_dict: dict):
|
||||||
|
file_public_path = row_dict.get('path')
|
||||||
|
path_list: List[str] = file_public_path.split('/')
|
||||||
|
original_name = path_list.pop()
|
||||||
|
file_id = path_list.pop()
|
||||||
|
save_file_path = path_join(env.file_save_path, file_id, original_name)
|
||||||
|
|
||||||
|
# 删除文件
|
||||||
|
try:
|
||||||
|
os.remove(save_file_path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("文件不存在:" + save_file_path)
|
||||||
|
|
||||||
|
# 删除文件夹
|
||||||
|
save_dir_path = path_join(env.file_save_path, file_id)
|
||||||
|
try:
|
||||||
|
os.rmdir(save_dir_path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print("文件夹不存在:" + save_dir_path)
|
||||||
|
|
||||||
|
return {"result": True}
|
||||||
|
|
||||||
|
@app.post('/save_file')
|
||||||
|
async def save_file(
|
||||||
|
file: UploadFile,
|
||||||
|
session: AsyncSessionDep,
|
||||||
|
head_id: str = Form(default=None, description="父对象id"),
|
||||||
|
attr1: str = Form(default=None, description="扩展属性1"),
|
||||||
|
attr2: str = Form(default=None, description="扩展属性2"),
|
||||||
|
attr3: str = Form(default=None, description="扩展属性3")
|
||||||
|
):
|
||||||
|
return await _save_file(session, file, {
|
||||||
|
"head_id": head_id,
|
||||||
|
"attr1": attr1,
|
||||||
|
"attr2": attr2,
|
||||||
|
"attr3": attr3
|
||||||
|
})
|
||||||
|
|
||||||
|
@app.post('/upload_file')
|
||||||
|
async def save_file(
|
||||||
|
file: UploadFile,
|
||||||
|
session: AsyncSessionDep,
|
||||||
|
head_id: str = Form(default=None, description="父对象id"),
|
||||||
|
attr1: str = Form(default=None, description="扩展属性1"),
|
||||||
|
attr2: str = Form(default=None, description="扩展属性2"),
|
||||||
|
attr3: str = Form(default=None, description="扩展属性3")
|
||||||
|
):
|
||||||
|
print("file", file)
|
||||||
|
print("head_id", head_id)
|
||||||
|
print("attr1", attr1)
|
||||||
|
print("attr2", attr2)
|
||||||
|
print("attr3", attr3)
|
||||||
|
|
||||||
|
result = await _save_file(session, file, {
|
||||||
|
"head_id": head_id,
|
||||||
|
"attr1": attr1,
|
||||||
|
"attr2": attr2,
|
||||||
|
"attr3": attr3
|
||||||
|
})
|
||||||
|
if 'result' in result:
|
||||||
|
print(f"upload_file:自动删除文件「{result['result']['path']}」")
|
||||||
|
await _delete_file(result['result'])
|
||||||
|
return result
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from fastapi import UploadFile
|
||||||
|
from sqlmodel import Field
|
||||||
|
|
||||||
|
from app.config.env import env
|
||||||
|
from app.model.BasicModel import BasicModel
|
||||||
|
from app.utils.create_module_service import create_model_service
|
||||||
|
from app.utils.db_utils import AsyncSessionDep
|
||||||
|
from app.utils.next_id import next_id
|
||||||
|
from app.utils.path_join import path_join
|
||||||
|
|
||||||
|
|
||||||
|
class FileModel(BasicModel, table=True):
|
||||||
|
__tablename__ = "pl_upload"
|
||||||
|
|
||||||
|
name: str = Field(default=None, description='文件名称')
|
||||||
|
path: str = Field(default=None, description='文件路径')
|
||||||
|
head_id: str = Field(default=None, description='父对象id')
|
||||||
|
attr1: str = Field(default=None, description='扩展属性1')
|
||||||
|
attr2: str = Field(default=None, description='扩展属性2')
|
||||||
|
attr3: str = Field(default=None, description='扩展属性3')
|
||||||
|
|
||||||
|
|
||||||
|
FileService = create_model_service(Cls=FileModel)
|
||||||
|
|
||||||
|
|
||||||
|
# 文件保存服务
|
||||||
|
class FileSaveService:
|
||||||
|
# 将文件保存到服务本地目录
|
||||||
|
# 并且往附件表中插入对应的文件记录
|
||||||
|
@staticmethod
|
||||||
|
async def saveFile(
|
||||||
|
session: AsyncSessionDep,
|
||||||
|
file: UploadFile,
|
||||||
|
filename: str,
|
||||||
|
id: str = None,
|
||||||
|
file_record: dict = None,
|
||||||
|
):
|
||||||
|
if not id:
|
||||||
|
id = await next_id()
|
||||||
|
|
||||||
|
datetime_string = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
|
||||||
|
file_id = f"{datetime_string}_{id}"
|
||||||
|
|
||||||
|
save_path = path_join(env.file_save_path, file_id).replace('\\', '/')
|
||||||
|
print("save_path", save_path)
|
||||||
|
|
||||||
|
public_path = path_join(env.file_public_path, file_id).replace('\\', '/')
|
||||||
|
print("public_path", public_path)
|
||||||
|
|
||||||
|
# parents=True 表示创建所有不存在的父目录
|
||||||
|
# exist_ok=True 表示如果目录已存在不抛出异常
|
||||||
|
Path(save_path).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
file_save_path = path_join(save_path, filename)
|
||||||
|
file_public_path = path_join(public_path, filename)
|
||||||
|
|
||||||
|
with open(file_save_path, 'wb') as f:
|
||||||
|
f.write(await file.read())
|
||||||
|
|
||||||
|
file_dict = {
|
||||||
|
"id": id,
|
||||||
|
"name": filename,
|
||||||
|
"path": file_public_path,
|
||||||
|
**file_record,
|
||||||
|
}
|
||||||
|
file_cls = await FileService.item_insert(session=session, row_dict=file_dict)
|
||||||
|
return {"result": file_cls.model_dump()}
|
||||||
@@ -6,6 +6,7 @@ from langserve import add_routes
|
|||||||
|
|
||||||
from app.config.env import env
|
from app.config.env import env
|
||||||
from app.controller.add_approve_route import add_approve_route
|
from app.controller.add_approve_route import add_approve_route
|
||||||
|
from app.controller.add_file_route import add_file_route
|
||||||
from app.controller.add_hotel_route import add_hotel_route
|
from app.controller.add_hotel_route import add_hotel_route
|
||||||
from app.controller.add_langgraph_approve_route import add_langgraph_approve_route
|
from app.controller.add_langgraph_approve_route import add_langgraph_approve_route
|
||||||
from app.controller.add_langgraph_chat_route import add_langgraph_chat_route
|
from app.controller.add_langgraph_chat_route import add_langgraph_chat_route
|
||||||
@@ -60,6 +61,7 @@ add_langgraph_chat_route(app)
|
|||||||
add_approve_route(app)
|
add_approve_route(app)
|
||||||
add_reimburse_route(app)
|
add_reimburse_route(app)
|
||||||
add_hotel_route(app)
|
add_hotel_route(app)
|
||||||
|
add_file_route(app)
|
||||||
|
|
||||||
|
|
||||||
@app.get("/get_env")
|
@app.get("/get_env")
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import os
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
def path_join(*pat_list: List[str]):
|
||||||
|
return os.path.join(*pat_list).replace('\\', '/')
|
||||||
Reference in New Issue
Block a user