提交的数据不是一个文件。请检查表单的编码类型

后端开发 2026-07-09

我当前正在用Postman测试一次上传多个文件(4张图片)。下面是在Postman中的配置方式。

此处输入图片描述

关键字段是file_list,值是我上传到Postman的这4 张图片文件。我把Django REST Framework的视图配置成如下:

class PostImageValidate(APIView):
    permission_classes = (IsAuthenticated, IsNotSuspended)

    def put(self, request):

        request_data = request.data.dict()
        serializer = TempImageSerializer(data=request_data)
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data
        file_list = data.get("file_list")
        uploaded_files = data.pop(file_list)

        results = []

        for file in uploaded_files:
            results.append({"filename": file.name, "size": file.size, "status": "Processed})

        return Response({"message": "Images processed successfully", "results": results, "number of items": len(results)}, status=status.HTTP_201_CREATED)
class TempImageSerializer(serializers.Serializer):
    file_list = serializers.ListField(child=serializers.FileField(max_length=150, allow_empty_file=False), allow_empty=False)

不过,在发出请求后,大约5 到6 秒,我得到了如下响应。

{
    "file_list": {
        "0": [
            "The submitted data was not a file. Check the encoding type on the form."
        ],
        "1": [
            "The submitted data was not a file. Check the encoding type on the form."
        ],
                 }
}
# The key "0" ,"1" extends up to 460 with the same statement above.

以上问题我还没能解决。我的目标是确保它按预期返回Response。只有在确认这一点后,我才打算开始处理这些文件,相关的处理代码尚未插入。

解决方案

我写了一个最小可运行的测试代码来验证,问题似乎出现在 .dict() 上。

request_data = request.data.dict()

它会创建一个只包含单个文件的字典(即使有多个文件)- 如下所示

{'file_list': <InMemoryUploadedFile: lenna.png (image/png)>}

但代码需要的是一个列表(即使只有一个文件)- 如下所示

{'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}

(因此后续它把这个单文件当作对象列表,从而在响应中产生了许多错误项)

如果跳过 .dict(),代码就能正确工作

request_data = request.data

# <QueryDict: {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>

或者如果你确实需要标准的 dict,而不是 QueryDict,就使用标准的 dict(...)

request_data = dict(request.data)

# {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>

也可以和 requests.FILES 一起工作

request_data = {"file_list": request.FILES.getlist("file_list")}

另一个问题出现在以下几行

file_list = data.get("file_list")
uploaded_files = data.pop(file_list)

它必须是字符串 "file_list",而不是变量 file_list

# no need to use `data.get()`
uploaded_files = data.pop("file_list")

用于测试的完整类

class PostImageValidate(APIView):
    # permission_classes = (IsAuthenticated, IsNotSuspended)

    def put(self, request):
        print("\n=== put ===\n")

        print("=== request.data ===")
        print(request.data)

        print("=== request.data.dict() ===")
        print(request.data.dict())

        print("=== request.data.lists() ===")
        print(request.data.lists())
        print(list(request.data.lists()))

        print("=== dict(request.data) ===")
        print(dict(request.data))

        print('=== request.FILES.getlist("file_list") ===')
        print(request.FILES.getlist("file_list"))

        # request_data = request.data.dict()   # WRONG
        # request_data = dict(request.data)
        request_data = request.data
        # request_data = {"file_list": request.FILES.getlist("file_list")}

        print("=== request_data ===")
        print(request_data)

        serializer = TempImageSerializer(data=request_data)
        serializer.is_valid(raise_exception=True)

        data = serializer.validated_data
        # uploaded_files = data.pop("file_list")
        uploaded_files = data.get("file_list")

        print("=== uploaded_files ===")
        print(uploaded_files)

        results = []

        for file in uploaded_files:
            results.append(
                {"filename": file.name, "size": file.size, "status": "Processed"}
            )

        output = {
            "message": "Images processed successfully",
            "results": results,
            "number of items": len(results),
        }

        return Response(output, status=status.HTTP_201_CREATED)

我在控制台(Linux Mint)用 curl 进行了测试

curl -X PUT \
  -F "[email protected]" \
  -F "[email protected]" \
  -F "other=Hello World!" \
  http://127.0.0.1:8000/api/upload/
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章