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

DRF FileUploadParser文件上传报错解决:缺失文件名400错误及添加参数后500错误处理

解决DRF FileUploadParser文件上传的400和500错误

让我一步步帮你拆解并解决这两个问题:

问题1:400 Bad Request - Missing filename

这个错误是FileUploadParser的硬性要求导致的——它期望请求的Content-Disposition头里必须明确携带filename参数。你需要在React的上传请求里正确配置这个请求头。

在React中用FormData上传文件时,注意不要手动设置Content-Type为multipart/form-data(浏览器会自动处理边界符),但要添加Content-Disposition头:

const formData = new FormData();
formData.append('file', selectedFile); // selectedFile是你从input获取的文件对象

axios.post('/api/activities/40/chapter/1/upload', formData, {
  headers: {
    'Content-Disposition': `attachment; filename="${selectedFile.name}"`
  }
});

这样DRF就能正确识别文件名,不会再抛出“Missing filename”的错误。

问题2:500 TypeError - post() missing required argument 'parameter'

这个错误的核心是URL路由参数和视图方法的参数不匹配。看你的请求路径/api/activities/40/chapter/1/upload,对应的URL配置应该是类似:

path('api/activities/<int:pk>/chapter/<int:chapterid>/upload', FileView.as_view(), name='file-upload')

但你的post方法参数是def post(self, request, format=None, *args, **kwargs):——虽然*args, **kwargs理论上能接收路由参数,但有时候DRF会因为参数声明不明确抛出错误。

解决方法很简单:要么显式声明参数,要么直接从kwargs里取值(不用绕parser_context):

方案1:显式声明参数

修改视图的post方法,把路由里的参数直接写进去:

def post(self, request, pk, chapterid, format=None):
    # 直接用pk和chapterid,不用再从parser_context取
    addAttr['activityid'] = pk
    addAttr['chapterid'] = chapterid
    # 其他代码不变

方案2:从kwargs直接取值

如果不想改方法签名,就把request.parser_context['kwargs']换成kwargs:

addAttr['activityid'] = kwargs['pk']
addAttr['chapterid'] = kwargs['chapterid']

这样就能避免参数缺失的错误了。

额外的代码优化建议

顺便给你提几个小优化点,让代码更规范:

  1. 文件名获取:你现在用request.data['filename'],其实request.FILES.get('file')本身就有name属性,直接用f.name更可靠。
  2. 序列化器传参:不用给序列化器传files=request.FILES,只要你的ChapterfileSerializer里定义了file字段(比如file = serializers.FileField()),直接把文件对象放到data里传给序列化器就行。
  3. 路径处理:用os.path.dirname()代替手动分割路径字符串,更安全:
    file_path = os.path.dirname(new_file_full_name)
    

修改后的简化视图代码参考:

class FileView(APIView):
    parser_classes = (FileUploadParser,)
    
    def post(self, request, pk, chapterid, format=None):
        file_obj = request.FILES.get('file')
        if not file_obj:
            raise ParseError("Empty content")
        
        new_file_full_name = file_upload_path(file_obj.name)
        serializer_data = {
            'activityid': pk,
            'chapterid': chapterid,
            'filepath': os.path.dirname(new_file_full_name),
            'filename': file_obj.name,
            'fileext': os.path.splitext(file_obj.name)[1],
            'create_date': datetime.datetime.now(),
            'file': file_obj  # 对应序列化器里的file字段
        }
        
        fileSerializer = ChapterfileSerializer(data=serializer_data)
        if fileSerializer.is_valid():
            fileSerializer.save()
            return Response(status=status.HTTP_201_CREATED)
        else:
            return Response(fileSerializer.errors, status=status.HTTP_400_BAD_REQUEST)

最后检查清单

  • 确认React请求的Content-Disposition头正确携带了filename
  • 验证URL路由的参数名(比如pk、chapterid)和视图方法的参数完全一致
  • 确保ChapterfileSerializer里包含了文件字段和其他需要的字段

内容的提问来源于stack exchange,提问作者floodnut

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 01:34:10