Limiting Upload File Size with Django Forms

A common use case in any web application is to allow users to upload files such as images, videos, PDFs, etc. But left unrestricted, this could lead to all sorts of problems including users uploading files that are too large for the system or application to handle.

File size restrictions can be placed on the upload in multiple ways including with JavaScript, web server configuration changes and within your application code. I definitely recommend using all of the above, but for this post, we’ll look at how to handle this in Django by subclassing Django’s FileField and ImageField form fields and adding some extra logic to the clean method.

First, define a max upload size within your settings (in bytes).

# Limit uploads to 5MB
MAX_UPLOAD_SIZE = 5242880

view raw
settings.py
hosted with ❤ by GitHub

Next, define the new fields (I usually stick these in app/forms/fields.py):

from django import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
class RestrictedFileField(forms.FileField):
def __init__(self, *args, **kwargs):
self.content_types = kwargs.pop('content_types', None)
self.max_upload_size = kwargs.pop('max_upload_size', None)
if not self.max_upload_size:
self.max_upload_size = settings.MAX_UPLOAD_SIZE
super(RestrictedFileField, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super(RestrictedFileField, self).clean(*args, **kwargs)
try:
if data.content_type in self.content_types:
if data.size > self.max_upload_size:
raise forms.ValidationError(_('File size must be under %s. Current file size is %s.') % (filesizeformat(self.max_upload_size), filesizeformat(data.size)))
else:
raise forms.ValidationError(_('File type (%s) is not supported.') % data.content_type)
except AttributeError:
pass
return data
class RestrictedImageField(forms.ImageField):
def __init__(self, *args, **kwargs):
self.max_upload_size = kwargs.pop('max_upload_size', None)
if not self.max_upload_size:
self.max_upload_size = settings.MAX_UPLOAD_SIZE
super(RestrictedImageField, self).__init__(*args, **kwargs)
def clean(self, *args, **kwargs):
data = super(RestrictedImageField, self).clean(*args, **kwargs)
try:
if data.size > self.max_upload_size:
raise forms.ValidationError(_('File size must be under %s. Current file size is %s.') % (filesizeformat(self.max_upload_size), filesizeformat(data.size)))
except AttributeError:
pass
return data

view raw
fields.py
hosted with ❤ by GitHub

You can now make use of these new fields from within your form class. Note that content_types is required for RestrictedFileField while max_upload_size is optional for both fields (defaults to whatever you specified for MAX_UPLOAD_SIZE in your settings).

image = RestrictedFileField(content_types=['video/quicktime', 'application/pdf']) # limit to QuickTime and PDF
image = RestrictedImageField(max_upload_size=2621440) # limit to 2.5MB

view raw
forms.py
hosted with ❤ by GitHub

And remember that the content-type is still user supplied (i.e. it’s a header coming from whatever submitted the form), so be sure to verify that the uploaded file contains the content-type you’re expecting.

2 thoughts on “Limiting Upload File Size with Django Forms”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s