
在 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 等标准操作。










