excel.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from fastapi import APIRouter, File, UploadFile, Depends
  2. from fastapi.responses import JSONResponse, FileResponse
  3. from fastapi.exceptions import HTTPException
  4. from sqlalchemy.orm import Session
  5. from starlette.websockets import WebSocket, WebSocketDisconnect
  6. from werkzeug.utils import secure_filename
  7. from app.api import get_current_user_websocket
  8. from app.models.agent_model import AgentModel, AgentType
  9. from app.models.base_model import get_db
  10. from app.models.user_model import UserModel
  11. from app.utils.excelmerge.conformity import run_conformity
  12. import shutil
  13. import os
  14. router = APIRouter()
  15. ALLOWED_EXTENSIONS = {'xlsx'}
  16. EXCEL_FILES_PATH = 'data/output'
  17. SOURCE_FILES_PATH = 'data/source'
  18. def allowed_file(filename):
  19. return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
  20. def create_dir_if_not_exists(path):
  21. if not os.path.exists(path):
  22. os.makedirs(path)
  23. # 清理函数
  24. def clear_directory(path):
  25. for filename in os.listdir(path):
  26. file_path = os.path.join(path, filename)
  27. try:
  28. if os.path.isfile(file_path) or os.path.islink(file_path):
  29. os.unlink(file_path)
  30. elif os.path.isdir(file_path):
  31. shutil.rmtree(file_path)
  32. except Exception as e:
  33. return {"error": "清空出错"}
  34. return {"message": "目录已清空"}
  35. @router.post('/excel/upload')
  36. async def upload_file(files: list[UploadFile] = File(...)):
  37. if not any(file.filename for file in files):
  38. return JSONResponse(content={"error": "没有文件部分"}, status_code=400)
  39. create_dir_if_not_exists(SOURCE_FILES_PATH)
  40. create_dir_if_not_exists(EXCEL_FILES_PATH)
  41. clear_directory(SOURCE_FILES_PATH)
  42. clear_directory(EXCEL_FILES_PATH)
  43. save_path_list = []
  44. for file in files:
  45. if file.filename == '':
  46. return JSONResponse(content={"error": "没有选择文件"}, status_code=400)
  47. if file and allowed_file(file.filename):
  48. filename = secure_filename(file.filename)
  49. save_path = os.path.join(SOURCE_FILES_PATH, filename)
  50. with open(save_path, 'wb') as buffer:
  51. shutil.copyfileobj(file.file, buffer)
  52. save_path_list.append(save_path)
  53. else:
  54. return JSONResponse(content={"error": "不允许的文件类型"}, status_code=400)
  55. return JSONResponse(content={"code": 200, "msg": "", "data": {}}, status_code=200)
  56. # ws://localhost:9201/api/document/ws/excel
  57. @router.websocket("/ws/excel")
  58. async def ws_excel(websocket: WebSocket):
  59. await websocket.accept()
  60. while True:
  61. data = await websocket.receive_text()
  62. try:
  63. if data == "合并Excel文件":
  64. clear_directory(EXCEL_FILES_PATH)
  65. output_file_path = run_conformity()
  66. await websocket.send_json({"step_message": "开始合并", "type": "stream", "files": []})
  67. elif data == "查询合并进度":
  68. files = os.listdir(EXCEL_FILES_PATH)
  69. if not files:
  70. await websocket.send_json({"step_message": "正在合并中", "type": "stream", "files": []})
  71. else:
  72. await websocket.send_json({"step_message": "文档合并成功!", "type": "stream", "files": []})
  73. elif data == "获取文件":
  74. files = os.listdir(EXCEL_FILES_PATH)
  75. if not files:
  76. await websocket.send_json({"error": "目录下没有生成的文件", "type": "stream", "files": []})
  77. else:
  78. first_file = files[0]
  79. file_name = os.path.basename(first_file)
  80. file_url = f"./api/document/download/{first_file}"
  81. await websocket.send_json({
  82. "step_message": "文档合并成功!",
  83. "type": "stream",
  84. "files": [{
  85. "file_name": file_name,
  86. "file_url": file_url
  87. }]
  88. })
  89. else:
  90. await websocket.send_json({"error": "未知指令"})
  91. except Exception as e:
  92. await websocket.send_json({"error": str(e)})
  93. @router.get("/download/{filename}")
  94. async def download_file(filename: str):
  95. try:
  96. return FileResponse(os.path.join(EXCEL_FILES_PATH, filename), filename=filename,
  97. media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
  98. except FileNotFoundError:
  99. raise HTTPException(status_code=404, detail="文件不存在")
  100. except Exception as e:
  101. raise HTTPException(status_code=500, detail="服务器错误")