Django REST Framework文件上传时文件损坏或request.data为空如何解决?
问题原因分析
- FileUploadParser导致文件损坏的原因:
FileUploadParser是DRF专门用于处理原始二进制文件流上传的解析器,要求请求体直接是文件的二进制内容,无额外表单封装。你使用form-data格式或者手动添加Content-Disposition头后,解析器会把整个请求体(包括请求头内容)全部写入文件,最终导致文件损坏无法打开。 - MultiPartParser下request.data为空的原因:存在两处错误:一是前端手动设置了
Content-Disposition头,覆盖了浏览器发送FormData时自动生成的带boundary分隔符的multipart/form-data请求头,后端无法正常解析表单内容;二是前后端表单字段名不匹配,后端代码取request.data['file'],但前端FormData里的键名是establishmentlogo。
修复后的实现代码
后端Django代码
from rest_framework.parsers import MultiPartParser, FormParser class EstablishmentMediaUploadView(views.APIView): permission_classes = (IsAuthenticated,) authentication_class = JSONWebTokenAuthentication # 替换解析器为表单解析器,适配form-data文件上传 parser_classes = (MultiPartParser, FormParser) serializer_class = MediaSerializer name = 'establishment-media-file-upload' def put(self, request, **kwargs): # 字段名和前端FormData的键名保持一致 if 'file' not in request.data: raise ParseError("Empty media file for establishment") establishmentid = kwargs.get('establishmentid') if not establishmentid: return Response({"error": "You didn't specify the establishmentid"}, status=400) try: establishment = Establishment.objects.get(id=establishmentid) except Establishment.DoesNotExist: return Response({"error": "Establishment not found"}, status=404) mediaFile = request.data.get('file') media = Media.objects.create(mediatitle=mediaFile.name) media.establishmentlogo.save(mediaFile.name, mediaFile, save=False) media.establishment = establishment media.save() return Response({"message": "Logo added for this establishment"}, status=200)
提示:请确保settings.py中已正确配置
MEDIA_ROOT和MEDIA_URL,保证文件可正常写入存储路径。
前端Angular代码
setEstablishmentLogo(establishment: Establishment, media: Media): Observable<Object> { let formdata = new FormData(); // 键名和后端取值的字段名保持一致为file formdata.set("file", media.establishmentlogo); var url = `${endpoints.establishment_media_upload_uri_base}/${establishment.id}`; return this.http.put(url, formdata, { headers: { 'Authorization': `Bearer ${token}` } }); }
重点:不要手动添加
Content-Type、Content-Disposition头,发送FormData时浏览器会自动生成符合规范的multipart/form-data请求头,手动设置会覆盖默认配置导致解析失败。
测试注意事项
- 使用接口测试工具(Insomnia/Thunder Client等)测试时,请求体选择
form-data格式,参数键名设为file,值类型选择File后上传本地文件,仅添加Authorization鉴权头即可,不要添加其他多余请求头。 - 前端测试时可通过浏览器控制台的网络面板查看请求头,确认
Content-Type为带boundary参数的multipart/form-data类型。
内容的提问来源于stack exchange,提问作者shellking4
相关产品推荐
相关产品推荐

