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

Django REST Framework文件接口格式校验:CSV/Excel上传报错排查

这个问题我之前碰到过,大概率是文件MIME类型的检测逻辑不够全面导致的——尤其是CSV文件,很多浏览器会把它识别为text/plain,而不是标准的text/csv,这就会触发你的类型验证错误。结合你的需求,我给你一套完整的解决方案:

问题定位

你看到的Wrong file type: text/plain错误,说明你的序列化器(serializer)里的文件类型验证逻辑,只允许了CSV文件的标准MIME类型text/csv,但忽略了浏览器可能发送的text/plain类型;同时可能没有结合文件扩展名做双重验证,导致判断不够准确。

解决方案

1. 完善序列化器的文件验证逻辑

在serializers.py里自定义验证方法,同时检查文件扩展名和真实MIME类型,这样既兼容浏览器的类型识别差异,又能防止伪造扩展名的恶意文件:

from rest_framework import serializers
from .models import File
import magic  # 需要安装依赖:pip install python-magic(Windows用pip install python-magic-bin)

class FileSerializer(serializers.ModelSerializer):
    class Meta:
        model = File
        fields = ['file', 'remark', 'timestamp']

    def validate_file(self, value):
        # 允许的文件扩展名
        allowed_extensions = ['csv', 'xls', 'xlsx']
        # 允许的MIME类型(包含CSV可能的text/plain)
        allowed_mime_types = [
            'text/csv',
            'text/plain',  # 兼容浏览器识别CSV为纯文本的情况
            'application/vnd.ms-excel',  # XLS格式
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'  # XLSX格式
        ]

        # 第一步:检查文件扩展名
        file_ext = value.name.split('.')[-1].lower()
        if file_ext not in allowed_extensions:
            raise serializers.ValidationError(f"不支持的文件格式:{file_ext},仅接受CSV、XLS、XLSX")

        # 第二步:检查文件真实MIME类型(避免伪造扩展名)
        mime_type = magic.from_buffer(value.read(1024), mime=True)
        value.seek(0)  # 重置文件指针,避免后续读取出错
        if mime_type not in allowed_mime_types:
            raise serializers.ValidationError(f"错误的文件类型:{mime_type}")

        return value

如果不想依赖python-magic,可以只做扩展名验证(安全性稍弱,但满足大多数场景):

def validate_file(self, value):
    allowed_extensions = ['csv', 'xls', 'xlsx']
    file_ext = value.name.split('.')[-1].lower()
    if file_ext not in allowed_extensions:
        raise serializers.ValidationError(f"不支持的文件格式:{file_ext},仅接受CSV、XLS、XLSX")
    return value

2. 确保API强制返回JSON响应

在视图层配置render_classes,强制接口返回JSON格式,同时配置文件上传所需的解析器:

from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import MultiPartParser, FormParser
from .serializers import FileSerializer
from .models import File

class FileUploadAPIView(generics.CreateAPIView):
    queryset = File.objects.all()
    serializer_class = FileSerializer
    renderer_classes = [JSONRenderer]  # 强制返回JSON格式
    parser_classes = [MultiPartParser, FormParser]  # 处理文件上传请求

    def create(self, request, *args, **kwargs):
        # 调用父类方法完成文件保存
        response = super().create(request, *args, **kwargs)
        # 自定义JSON响应内容
        return Response({
            'code': 201,
            'message': '文件上传成功',
            'data': {
                'file_id': response.data['id'],
                'file_name': response.data['file'],
                'remark': response.data['remark']
            }
        }, status=status.HTTP_201_CREATED)

3. 测试验证

上传CSV文件时,即使浏览器发送text/plain的MIME类型,也会因为我们把它加入了允许列表,同时扩展名是.csv,所以能通过验证;Excel文件的MIME类型和扩展名也都被覆盖,不会再出现类型错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:44:47