attachment.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import mimetypes
  2. from io import BytesIO
  3. from typing import List
  4. from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, status
  5. from fastapi.responses import StreamingResponse
  6. from sqlalchemy.orm import Session
  7. from app.database import get_db
  8. from app.core.deps import get_current_user
  9. from app.models.user import User
  10. from app.schemas.common import ApiResponse
  11. from app.schemas.attachment import AttachmentOut
  12. from app.services.attachment import AttachmentService
  13. from app.services.minio import MinioService
  14. router = APIRouter(prefix="/api/attachments", tags=["附件管理"])
  15. @router.post("/upload", response_model=ApiResponse[AttachmentOut])
  16. def upload_file(
  17. file: UploadFile = File(...),
  18. biz_type: str = "",
  19. biz_id: int = 0,
  20. db: Session = Depends(get_db),
  21. current_user: User = Depends(get_current_user),
  22. ):
  23. file_data = file.file.read()
  24. content_type = file.content_type or mimetypes.guess_type(file.filename or "")[0] or "application/octet-stream"
  25. object_name = MinioService.upload_file(file.filename or "unknown", file_data, content_type)
  26. data = {
  27. "biz_type": biz_type,
  28. "biz_id": biz_id,
  29. "file_name": file.filename or "unknown",
  30. "file_path": object_name,
  31. "file_type": content_type,
  32. "file_size": len(file_data),
  33. "create_by": str(current_user.id),
  34. }
  35. attachment = AttachmentService.create(db, data)
  36. return ApiResponse(data=AttachmentOut.model_validate(attachment))
  37. @router.get("/download/{attachment_id}")
  38. def download_file(
  39. attachment_id: int,
  40. db: Session = Depends(get_db),
  41. current_user: User = Depends(get_current_user),
  42. ):
  43. attachment = AttachmentService.get_by_id(db, attachment_id)
  44. if not attachment:
  45. raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="附件不存在")
  46. file_data = MinioService.download_file(attachment.file_path)
  47. file_stream = BytesIO(file_data)
  48. headers = {"Content-Disposition": f"attachment; filename={attachment.file_name}"}
  49. return StreamingResponse(file_stream, media_type=attachment.file_type or "application/octet-stream", headers=headers)
  50. @router.get("/list", response_model=ApiResponse[List[AttachmentOut]])
  51. def list_by_biz(
  52. biz_type: str = "",
  53. biz_id: int = 0,
  54. db: Session = Depends(get_db),
  55. current_user: User = Depends(get_current_user),
  56. ):
  57. attachments = AttachmentService.get_by_biz(db, biz_type=biz_type, biz_id=biz_id)
  58. return ApiResponse(data=[AttachmentOut.model_validate(a) for a in attachments])