1

My Headers from Postmanenter image description here- I have endpoint which successfully upload to AWS s3 bucket image but when I try to upload more than 1 file, It upload last one. How can I fix that?enter image description here

My view:

class MediaViewSet(mixins.CreateModelMixin,
                   viewsets.GenericViewSet):
    queryset = Media.objects.all()
    serializer_class = MediaSerializer
    permission_classes = (IsAuthenticated,)

My serializers:

class MediaSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.Media
        fields = ('uploaded_at', 'upload')

My Model:

class Media(models.Model):
    uploaded_at = models.DateTimeField(auto_now_add=True)
    upload = models.FileField(storage=MediaStorage())
alexuuu
  • 53
  • 5

1 Answers1

1

I've never done this but I think it should be handled by the browser via headers.

So RFC 7587 says

4.3. Multiple Files for One Form Field

The form data for a form field might include multiple files.

[RFC2388] suggested that multiple files for a single form field be transmitted using a nested "multipart/mixed" part. This usage is deprecated.

To match widely deployed implementations, multiple files MUST be sent by supplying each file in a separate part but all with the same "name" parameter.

Receiving applications intended for wide applicability (e.g.,
multipart/form-data parsing libraries) SHOULD also support the older
method of supplying multiple files.

So I think you will just have to post with

Content-Type: multipart/form-data; boundary=something; name="file"

More about boundaries in mozilla docs or SO.


Can you list all the headers you send?

Ok, so your headers are correct. You have a few options.

  1. This idea doesn't sound good. If possible, upload files one by one as POST should return 1 new entity.
  2. Overwrite create method and when you initialize serializer pass many=True to it or create them one by one.
  3. Create a separate view, something as UploadMultipleFiles(GenericViewSet) where you will have a total control over what's happening.
  4. Or even UploadMultipleFiles(CreateAPIView).

I think you should pick the 2nd option so something like this should work

    def perform_create(self, serializer):
        return serializer.save()

    def create(self, request, *args, **kwargs):
        uploaded_files = []

        for uploaded_file in request.FILES:
            serializer = self.get_serializer(upload=uploaded_file)
            serializer.is_valid(True)
            instance = self.perform_create(serializer)
            uploaded_files.append(instance)

        response_serializer = self.get_serializer(uploaded_files, many=True)
        headers = self.get_success_headers(response_serializer.data)
        return Response(response_serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Community
  • 1
  • 1
Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44