Max image size on file upload
Asked Answered
F

3

50

I have an ImageField in my form. How would I enforce a file size min/max, something like --

image = forms.ImageField(max_size = 2MB) 

or

image = forms.ImageField(min_size = 100k)

Thank you.

Flameproof answered 1/6, 2011 at 2:0 Comment(1)
possible duplicate of Django File upload size limitNeddra
T
59

models.py

class Product(models.Model):
    image = models.ImageField(upload_to="/a/b/c/")

forms.py

class ProductForm(forms.ModelForm):
    # Add some custom validation to our image field
    def clean_image(self):
        image = self.cleaned_data.get('image', False)
        if image:
            if image._size > 4*1024*1024:
                raise ValidationError("Image file too large ( > 4mb )")
            return image
        else:
            raise ValidationError("Couldn't read uploaded image")
Teens answered 1/6, 2011 at 2:57 Comment(5)
There should not be a colon after line 4 in the forms.py code, but it won't let me make a change less than 6 characters. Be careful if you are copying and pasting this code (not that you should copy+paste any code).Scraggy
If anyone is interested in this answer, I've written a blog post that touches on image validation when uploading an image via an URLWaterfall
Wait, does this upload the whole image first or does it have to come through first? Will the http server i.e. nginx not catch this as a 413 before this validation can occur?Carrero
Django will check the file limit size condition only after the file is completely uploaded to the server. So to avoid the unnecessary traffic usage, you need to implement either client check or apache check.Land
it should be .size not ._sizeCapstone
S
56

Essentially this is a duplicate of Django File upload size limit

You have two options:

  1. Use validation in Django to check the uploaded file's size. The problem with this approach is that the file must be uploaded completely before it is validated. This means that if someone uploads a 1TB file, you'll probably run out of hard drive space before the user gets a form error.

  2. Configure the Web server to limit the allowed upload body size. e.g. if using Apache, set the LimitRequestBody setting. This will mean if a user tries to upload too much, they'll get an error page configurable in Apache

As @pastylegs says in the comments, using a combination of both is probably the best approach. Say you want a maximum of 5MB, perhaps enforce a 20MB limit at the Web server level, and the 5MB limit at the Django level. The 20MB limit would provide some protection against malicious users, while the 5MB limit in Django provides good UX.

Sabella answered 1/6, 2011 at 2:33 Comment(2)
A mix of both is probably a good idea. Limit all uploads to something sensible via apache/nginx etc (50mb maybe) and then make it more specific at the application levelWaterfall
@pastylegs I agree, this is the approach I would take too.Sabella
G
29

Here is another option that I didn't see across the variations of this question on stackoverflow: use a custom validator in your models. If you use this technique and a ModelForm in forms.py, then this should be all you need.

models.py

from django.core.exceptions import ValidationError

class Product(models.Model):
    def validate_image(fieldfile_obj):
        filesize = fieldfile_obj.file.size
        megabyte_limit = 5.0
        if filesize > megabyte_limit*1024*1024:
            raise ValidationError("Max file size is %sMB" % str(megabyte_limit))

    image = models.ImageField(upload_to="/a/b/c/", validators=[validate_image])
Gers answered 5/1, 2014 at 22:59 Comment(1)
Just to clarify, this would upload the file in full first before validating, correct? In which case I agree with bradley.ayers, you should also set a web server limitPickax

© 2022 - 2024 — McMap. All rights reserved.