4

I have a Django project that requires users to use add multiple images to a post article. I am using django and deploying it using zappa. I know that in Zappa the maximum size in the page load is 10mb. I have 1 post image and 7 prep images. When user adds 7 large files and then hits submit I get the error below

HTTP413: PAYLOAD TOO LARGE - The server is refusing to process a request because the request entity is larger than the server is willing or able to process.

Is there a way in which the images are added one by one instead of all at once so the form does not break and I don't get the above error

class Post(models.Model):
    user = models.ForeignKey(User, related_name='posts')    
    title = models.CharField(max_length=250, unique=True)
    message = models.TextField()
    post_image = models.ImageField(upload_to='post_images/')

    def save(self, *args, **kwargs):
        im = Image.open(self.post_image)
        super(Post, self).save()
        output = BytesIO()
        basewidth = 700
        wpercent = (basewidth / float(im.size[0]))
        hsize = int((float(im.size[1]) * float(wpercent)))
        im = im.resize((basewidth, hsize))
        # after modifications, save it to the output
        im.save(output, format='JPEG', quality=40)
        output.seek(0) 
        self.post_image = InMemoryUploadedFile(output, 'ImageField', "%s.jpg" % self.post_image.name.split('.')[0], 'image/jpeg',
                                          sys.getsizeof(output), None)
        super().save(*args, **kwargs)

Then I have the model that adds multiple images to the post

class Prep (models.Model): #(Images)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='post_prep')
    image = models.ImageField(upload_to='post_prep_images/', blank=True, null=True)
    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        im = Image.open(self.image)
        output = BytesIO()
        basewidth = 700
        wpercent = (basewidth / float(im.size[0]))
        hsize = int((float(im.size[1]) * float(wpercent)))
        super(Prep, self).save()
        im = im.resize((basewidth, hsize))
        # after modifications, save it to the output
        im.save(output, format='JPEG', quality=300)
        output.seek(0)

        # change the imagefield value to be the newley modifed image value
        self.image = InMemoryUploadedFile(output, 'ImageField', "%s.jpg" % self.image.name.split('.')[0], 'image/jpeg',
                                        sys.getsizeof(output), None)

        super(Prep, self).save()

In my views.py both the models are merged to create 1 form

@login_required
def post_create(request):
    ImageFormSet = modelformset_factory(Prep, fields=('image', 'image_title', 'image_description'), extra=7, max_num=7,
                                        min_num=2)
    if request.method == "POST":
        form = PostForm(request.POST or None, request.FILES or None)
        formset = ImageFormSet(request.POST or None, request.FILES or None)
        if form.is_valid() and formset.is_valid():
            instance = form.save(commit=False)
            instance.user = request.user
            instance.save()
            post_user = request.user
            for f in formset.cleaned_data:
                try:
                    photo = Prep(post=instance, image=f['image']
                    photo.save()
                except Exception as e:
                    break
            return redirect('posts:single', username=instance.user.username, slug=instance.slug)
    else:
        form = PostForm()
        formset = ImageFormSet(queryset=Prep.objects.none())
    context = {
        'form': form,
        'formset': formset,
    }
    return render(request, 'posts/post_form.html', context)
Samir Tendulkar
  • 761
  • 1
  • 10
  • 36

1 Answers1

3

10 MB limit is not a Zappa limit, but an API gateway limit. And it, being a limit set by AWS there is no way to increase it.

You could go down a rather complex route of uploading large payloads through API gateway to S3. It is explained in detail in this article: https://sookocheff.com/post/api/uploading-large-payloads-through-api-gateway/

Or you could do some frontend magic and make several smaller requests, one for each photo you are uploading.

mislavcimpersak
  • 2,370
  • 28
  • 28
  • I am may hold off on my severless dreams for sometime – Samir Tendulkar Feb 19 '19 at 04:31
  • 1
    This limitation is a big deal for those who might think that AWS Lambda is a realistic and relatively straightforward option for deploying typical Django applications (as well you might from reading some of the literature). Things that are normally pretty simple like preparing thumbnails from a user-uploaded image will require you to substantially re-tool. – Alexander Jun 09 '19 at 11:05