messages_upload.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. from fastapi import APIRouter, UploadFile, File, HTTPException, Depends
  2. from typing import List
  3. from app.api.v1 import deps
  4. from app.models.user import User
  5. from app.core.minio import minio_storage
  6. router = APIRouter()
  7. # 允许的文件类型白名单
  8. ALLOWED_MIME_TYPES = {
  9. "image/jpeg", "image/png", "image/gif", "image/webp", # 图片
  10. "video/mp4", "video/quicktime", "video/x-msvideo", # 视频
  11. "application/pdf", "application/msword", # 文档
  12. "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  13. "application/vnd.ms-excel",
  14. "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  15. "text/plain"
  16. }
  17. MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB
  18. @router.post("/upload", summary="上传消息附件")
  19. async def upload_message_attachment(
  20. file: UploadFile = File(...),
  21. current_user: User = Depends(deps.get_current_active_user)
  22. ):
  23. """
  24. 上传图片/视频/文件用于发送消息。
  25. """
  26. # 2. 读取文件内容
  27. content = await file.read()
  28. if len(content) > MAX_FILE_SIZE:
  29. raise HTTPException(status_code=400, detail="文件大小超过 50MB 限制")
  30. # 3. 上传到 MinIO
  31. try:
  32. filename = file.filename
  33. # 调用 minio_storage.upload_message_file
  34. # 注意:这里需要确保 minio_storage.upload_message_file 支持 file_data 参数为 bytes
  35. object_name = minio_storage.upload_message_file(
  36. file_data=content,
  37. filename=filename,
  38. content_type=file.content_type,
  39. user_id=current_user.id
  40. )
  41. # 生成预签名 URL (1小时有效)
  42. presigned_url = minio_storage.get_presigned_url(object_name)
  43. except Exception as e:
  44. raise HTTPException(status_code=500, detail=str(e))
  45. # 4. 返回结果
  46. return {
  47. "url": presigned_url,
  48. "key": object_name,
  49. "filename": file.filename,
  50. "content_type": file.content_type,
  51. "size": len(content)
  52. }