endpoints.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. # app/api/endpoints.py
  2. from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Query
  3. from fastapi.responses import StreamingResponse
  4. from typing import List
  5. import urllib.parse
  6. from app.models.schemas import FileItem, CreateFolderRequest
  7. from app.services.minio_service import minio_service
  8. from minio.error import S3Error
  9. router = APIRouter()
  10. @router.get("/files", response_model=List[FileItem])
  11. async def list_files(path: str = "/"):
  12. try:
  13. return minio_service.list_files(path)
  14. except S3Error as e:
  15. raise HTTPException(status_code=500, detail=str(e))
  16. # 在 app/api/endpoints.py 中修改 upload_file 接口
  17. @router.post("/upload")
  18. async def upload_file(
  19. file: UploadFile = File(...),
  20. path: str = Form(...)
  21. ):
  22. """
  23. path: 完整的文件路径 (例如: folder/subfolder/image.png)
  24. """
  25. try:
  26. # 调试信息
  27. print(f"上传文件: {file.filename}, 目标路径: {path}")
  28. # 确保路径不以 / 开头(MinIO 规范)
  29. if path.startswith('/'):
  30. path = path[1:]
  31. # 获取文件大小
  32. # 获取文件大小 (UploadFile 的 spool_max_size 后会存入磁盘或内存)
  33. # 为了稳妥起见,移动指针到最后获取大小,再移回
  34. file.file.seek(0, 2)
  35. size = file.file.tell()
  36. file.file.seek(0)
  37. minio_service.upload_file(
  38. file.file,
  39. path,
  40. file.content_type or "application/octet-stream",
  41. size
  42. )
  43. return {"message": "Upload successful", "filename": file.filename, "path": path}
  44. except Exception as e:
  45. print(f"上传错误: {str(e)}")
  46. raise HTTPException(status_code=500, detail=str(e))
  47. @router.post("/folder")
  48. async def create_folder(req: CreateFolderRequest):
  49. try:
  50. minio_service.create_folder(req.path)
  51. return {"message": "Folder created"}
  52. except S3Error as e:
  53. raise HTTPException(status_code=500, detail=str(e))
  54. @router.get("/download")
  55. async def download_file(path: str):
  56. try:
  57. data_stream = minio_service.get_file_stream(path)
  58. filename = path.split("/")[-1]
  59. quoted_filename = urllib.parse.quote(filename)
  60. return StreamingResponse(
  61. data_stream,
  62. media_type="application/octet-stream",
  63. headers={
  64. "Content-Disposition": f"attachment; filename*=UTF-8''{quoted_filename}"
  65. }
  66. )
  67. except Exception as e:
  68. raise HTTPException(status_code=404, detail="File not found or error")
  69. @router.delete("/delete")
  70. async def delete_item(path: str):
  71. try:
  72. is_dir = path.endswith("/")
  73. minio_service.delete_file(path, is_dir)
  74. return {"message": "Deleted successfully"}
  75. except S3Error as e:
  76. raise HTTPException(status_code=500, detail=str(e))
  77. @router.get("/preview")
  78. async def preview_file(path: str):
  79. try:
  80. url = minio_service.get_presigned_url(path)
  81. return {"url": url}
  82. except Exception as e:
  83. raise HTTPException(status_code=500, detail=str(e))
  84. @router.get("/storage-info")
  85. async def get_storage_info():
  86. try:
  87. return minio_service.get_storage_info()
  88. except S3Error as e:
  89. raise HTTPException(status_code=500, detail=str(e))