如何在 Django 中正确获取通过 FormData 上传的文件对象

8次阅读

如何在 Django 中正确获取通过 FormData 上传的文件对象

在 django rest framework 中,使用 `request.post.get(“file”)` 无法获取上传的文件,因为文件实际存储在 `request.files` 中,而非 `post`;需通过 `request.files[‘file’]` 访问,并确保视图正确处理 multipart/form-data 请求。

前端使用 FormData.append(“file”, file) 发送文件时,django 并不会将该字段放入 request.POST,而是统一归入 request.FILES —— 这是 Django 对文件上传的标准设计。你当前的代码:

file = request.POST.get("file")  # ❌ 总是 None

应改为:

from rest_framework.decorators import api_view from rest_framework.response import Response  @api_view(["POST"]) def jobs(request):     # ✅ 正确获取 jsON 元数据(字符串)     metadata_str = request.POST.get("metadata")     if not metadata_str:         return Response({"error": "missing metadata"}, status=400)      try:         import json         metadata = json.loads(metadata_str)     except json.JSONDecodeError:         return Response({"error": "invalid metadata JSON"}, status=400)      # ✅ 正确获取上传的文件对象(InMemoryUploadedFile 或 TemporaryUploadedFile)     uploaded_file = request.FILES.get("file")     if not uploaded_file:         return Response({"error": "no file uploaded"}, status=400)      print("Metadata:", metadata)     print("File name:", uploaded_file.name)           # e.g., "image.png"     print("File size:", uploaded_file.size)           # bytes     print("Content type:", uploaded_file.content_type) # e.g., "image/png"      # ✅ 示例:安全保存文件(生产环境建议用 django-storages 或异步处理)     from django.core.files.base import ContentFile     import os     from pathlib import Path      upload_dir = Path("media/uploads/")     upload_dir.mkdir(exist_ok=True)     file_path = upload_dir / uploaded_file.name      with open(file_path, "wb+") as destination:         for chunk in uploaded_file.chunks():  # 防止大文件内存溢出             destination.write(chunk)      return Response({         "message": "upload success",         "file_url": f"/media/uploads/{uploaded_file.name}"     })

⚠️ 关键注意事项

  • 请求头无需手动设置axios.post(…, formData) 会自动设置 Content-Type: multipart/form-data; boundary=…,切勿手动覆盖(如 headers: {‘Content-Type’: ‘multipart/form-data’}),否则会导致解析失败。
  • Django 配置检查
    • 确保 settings.py 中包含 ‘django.middleware.csrf.CsrfViewMiddleware’(若禁用 CSRF,请显式添加 @csrf_exempt 或使用 @api_view + authentication_classes=[] 配合 permission_classes=[AllowAny]);
    • FILE_UPLOAD_MAX_MEMORY_SIZE 和 DATA_UPLOAD_MAX_MEMORY_SIZE 应足够支持你的文件大小;
  • 前端可选增强(提升健壮性):
    // 添加错误处理与类型校验 formData.append("file", file); if (!file.type.startsWith("image/")) {     alert("Please select an image file");     return; }

✅ 总结:文件永远在 request.FILES,不在 request.POST;request.POST 仅包含文本字段(如 metadata 字符串),而二进制文件由 Django 自动解析并封装为 InMemoryUploadedFile 实例,支持 .read(), .chunks(), .name 等标准操作。

text=ZqhQzanResources