Custom FileField with content type and size validation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# extra.py in yourproject/app/

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
        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.'))

        return data

More like this

  1. Validate by file content type and size by macmichael01 4 years, 4 months ago
  2. Amazon S3 browser-based upload form(FIXED) by grillermo 8 months, 2 weeks ago
  3. Aggiornare i Content Types e i Permessi del Model di una Tabella nell Admin by dario.agliottone 1 year, 1 month ago
  4. Update ContentTypes and Permissions without syncdb by paltman 5 years, 2 months ago
  5. Database file storage by powerfox 4 years, 4 months ago

Comments

gsakkis (on September 27, 2010):

First off this is a dupe of #1303. Second, as #1303 it fails to prevent the upload of huge files, it just rejects them after they have been uploaded. The effective way to limit the file size (at least at the Django level) is using something like http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/file_uploads/uploadhandler.py, with the downside that it abruptly terminates the connection instead of showing a user friendly Validation error.

#

nemesis (on September 27, 2010):

Thanks for the info.

Is not exactly a duplicated of 1303, even if I used the main part of that. 1303 is a custom validation while this is a custom file field that can be used in the admin too.

How would you advice to implement the method you linked?

#

gsakkis (on September 27, 2010):

I'd love to be proven wrong but I believe there is no way to get a nice validation error without uploading the whole file; otherwise the browser throws "The connection to the server was reset while the page was loading" on Firefox (or "Error 101 (net::ERR_CONNECTION_RESET): Unknown error" on Chrome).

#

nemesis (on September 30, 2010):

So would it be possible then to add a line in the end that deletes the file? I'll try it out..

#

nemesis (on September 30, 2010):

The files is stored only in the temporary directory.

I think it's a good solution to use both this filefield and set FILE_UPLOAD_MAX_MEMORY_SIZE in your settings.py file so it allows a size that is slight larger than the model field.

#

gsakkis (on October 1, 2010):

If you're ok with letting people use up all your bandwidth for uploading 1GB files to your servers just to delete them as soon as the upload finishes, sure it's a great solution :-P

Here is a StackOverflow answer than does a much better job than me to explain the problem: http://stackoverflow.com/questions/674651/uploading-files-past-asp-net-request-length-limit/679427#679427

#

byroncorrales (on October 1, 2010):

For get it work with south migrations I had to changed some lines...

def __init__(self, content_types=None, max_upload_size=None, **kwargs):
    self.content_types = content_types
    self.max_upload_size = max_upload_size
    super(ContentTypeRestrictedFileField, self).__init__(**kwargs)

And adding the specific rule for south and the end of the file

from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^app\.extra\.ContentTypeRestrictedFileField"])

#

eos87 (on October 4, 2010):

it works for me!, but i recommend add the project name to the instrospection_rule path, something like this:

from south.modelsinspector import add_introspection_rules add_introspection_rules([], ["^project_name.app.extra.ContentTypeRestrictedFileField"])

#

eos87 (on October 4, 2010):

oops! i forgot the slashes!!

from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^project_name\.app\.extra\.ContentTypeRestrictedFileField"])

#

eos87 (on October 5, 2010):

there is a bug, when you try to update a registry in admin panel, and do not update the field with ContentTypeRestrictedFileField you will get an error of content_type value.

here is the source of clean method of ContentTypeRestrictedFileField class fixed.

http://paste.ubuntu.com/506762/

#

nemesis (on October 30, 2010):

@gsakkis

I designed this field to use it in the admin so i'm not worried about 1GB file because the users are already trusted.

For who's worried about huge files: configure the max upload limit in apache.

#

sv1jsb (on February 18, 2011):

I am new in Django but I would like to ask this, reading your code.

You import FileField from models but FileField in models doesn't have a clean method.

FileField from forms have one.

You have been using this snippet as it is and it worked without a problem?

#

dokterbob (on August 31, 2011):

A new & dusted off version, checking minimum size, maximum size, matching extensions and mime types.

https://gist.github.com/1183767

#

AguirreLORETTA27 (on March 14, 2012):

Some time ago, I needed to buy a building for my business but I didn't have enough cash and could not purchase anything. Thank heaven my father proposed to try to take the loans at banks. Thus, I acted so and was satisfied with my collateral loan.

#

(Forgotten your password?)