[Django]-Set image size limit and resize image if is needed

8👍

✅

There is a LOT of conversation that could go into this. On the other hand there are essentially two separate issues for worrying about image size checking. 1) client side and 2) server side. So let’s break that up.

Server Side

This is the most important part of the two. Yes, the client side can help reduce the size of the image or inform the user that the image they attempted to upload is too large, but ultimately you want the server to decide what is acceptable.

So, in Django, theres a few things you can do.

1) limit file size – In your settings, you can place the following code

# Add to your settings file
MAX_UPLOAD_SIZE = "1048576"

Make an image size checker like the following, and run it to to check the size of ‘image_field’ (name may change). This code returns a validation error if ‘image_field’ is too large.

#Add to a form containing a FileField and change the field names accordingly.
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
from django.conf import settings

def check_image_field_size(self):
    content = self.cleaned_data.get('image_field')
    if content._size > settings.MAX_UPLOAD_SIZE:
        raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(settings.MAX_UPLOAD_SIZE), filesizeformat(content._size)))
    return content

source

this will keep uploaded file sizes from exceeding 1MB, period.

2) resize the image – Using PIL (Pillow), resize the image.

import StringIO
from PIL import Image
from io import BytesIO

# get the image data from upload
image_field = self.cleaned_data.get('image_field')
image_file = StringIO.StringIO(image_field.read())
image = Image.open(image_file)

# like you said, cut image dimensions in half
w, h = image.size
image = image.resize((w/2, h/2), Image.ANTIALIAS)

# check if the image is small enough 
new_img_file = BytesIO()
image.save(new_img_file, 'png')
image_size = new_img_file.tell() 

# if the image isn't small enough, repeat the previous until it is.

3) Lossy compresss the image

 # assuming you already have the PIL Image object (im)
 quality_val = 90
 new_img_file = BytesIO()
 im.save(filename, 'JPEG', quality=quality_val)
 image_size = new_img_file.tell()
 # if image size is too large, keep repeating

Client Side

Really, the client side only makes things more straightforward for the user. You can try implementing this stuff on the client side, but if you rely on it, there is always the possibility of someone bypassing your client side setup and uploading a 10TB sized ‘image’ (Some people just want to watch the world burn).

1) resize or compress – Same as above, but using Javascript or Jquery.

2) cropping – JCrop is a library that I have used before. It takes some work but it is useful. You can help the user crop the image to a size that is more appropriate and also to give them more power over how the image looks at the new resolution.

2) helpful messages – If the image a user is uploading is too large, let them know.

Sources

How to get image size in python-pillow after resize?

How do I resize an image using PIL and maintain its aspect ratio?

How to adjust the quality of a resized image in Python Imaging Library?

1👍

Images can also be limited in the models.py.

Place a function something like this in your models.py.

def validate_image(image):
    file_size = image.file.size
    limit_kb=settings.LIMIT_KB
    if file_size > limit_kb * 1024:
        raise ValidationError("Max size of file is %s KB" % limit_kb)

This assumes you have:

from django.core.exceptions import ValidationError

It also assumes you have made a constant LIMIT_KB in settings.py.

Then when adding the field include validation:

image = models.ImageField(upload_to=image_path,validators=[validate_image])

The image size will now be limited by the model and caught when using a form.

Leave a comment