Blog

Accept Only Specific File Types in Django File Upload

Written by Staff | Jan 14, 2012 8:00:00 AM

Accept Only Specific File Types in Django

There are times that we only have to accept specific file types and limit file size in our file uploads. This time, I am going to show simple steps to make a FileField accept only specific file types.

Assuming that we already have a working model, views and template(s) are already working.

Step 1:

Create a file and name it formatChecker.py. This is the code for your formatChecker.py:

from django.db.models import FileField
from django.forms import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _

class ContentTypeRestrictedFileField(FileField):
    """
    Same as FileField, but you can specify:
        * content_types - list containing allowed content_types.
        Example: ['application/pdf', 'image/jpeg']
        * max_upload_size - a number indicating the maximum file
        size allowed for upload.
            2.5MB - 2621440
            5MB - 5242880
            10MB - 10485760
            20MB - 20971520
            50MB - 5242880
            100MB 104857600
            250MB - 214958080
            500MB - 429916160
    """
    def __init__(self, *args, **kwargs):
        self.content_types = kwargs.pop("content_types")
        self.max_upload_size = kwargs.pop("max_upload_size")

        super(ContentTypeRestrictedFileField, self).__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs)
        file = data.file
        try:
            content_type = file.content_type
            if content_type in self.content_types:
                if file._size > self.max_upload_size:
                    raise forms.ValidationError(_('Please keep filesize under'
                                                '%s. Current filesize %s')
                                                % (filesizeformat(self.max_upload_size), filesizeformat(file._size)))
            else:
                raise forms.ValidationError(_('Filetype not supported.'))
        except AttributeError:
            pass

        return data

We are now done with step 1. Basically, what formatChecker.py does is it overrides the FileField class. What that snippet does is it checks the file type of the file and checks the file size during the process of form validation. It returns error messages if a user uploaded an invalid file.

Step 2:

Change your field “FileField” to “ContentTypeRestrictedFileField”.

To make things more clear, I’ll show you an example.

Example:

class Archive(models.Model):
    title = models.CharField(max_length=245)
    # some other fields here
    attached_file = ContentTypeRestrictedFileField(upload_to='uploads/', content_types=['application/msword', 'application/pdf', 'application/vnd.oasis.opendocument.text'],max_upload_size=5242880,blank=True, null=True)

For the first value of the parameter of  ContentTypeRestrictedFileField, “upload_to”, this is where the file goes when uploaded. The second value, “content_types”, is a list of accepted file types. The third value is the  allowed maximum size of the file.

That’s it. We can now restrict file types that we do not want to be uploaded.