Django rest framework response : "The submitted data was not a file. Check the encoding type on the form."

I'm currently testing uploading multiple files(4 images) at once using Postman. Here is how's its configured on Postman.

enter image description here

The key is file_list and the values are the 4 image files I've uploaded to postman. I've configured My Django rest framework view like the following :

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)

However, I get the following response after a span of 5-6 seconds of making a request.

{
    "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.

I haven't been able to solve the above. My objective is to make sure it returns the Response as expected. Only then I intend to move onto my end of processing those files, the code for which hasn't been inserted.

I made minimal working code for test it and it seems problem makes .dict() in

request_data = request.data.dict()

It creates dictionary with single file (even if there are more files) - like this

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

but code needs list (even if there is only one file) - like this

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

(so later it treats this single file as list of objects and it creates so many wrong items in response)

Code works correctly if I skip .dict()

request_data = request.data

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

or I use standard dict(...) if you really need standard dict instead of QueryDict

request_data = dict(request.data)

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

Works also with requests.FILES

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

Other problem is in lines

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

It has to be string "file_list" instead of variable file_list

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

Full class used for tests

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)

I tested it with curl in console (on Linux Mint)

curl -X PUT \
  -F "file_list=@lenna.jpg" \
  -F "file_list=@lenna.png" \
  -F "other=Hello World!" \
  http://127.0.0.1:8000/api/upload/
Вернуться на верх