You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 17:21:02