# 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
Comments
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.
#
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?
#
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).
#
So would it be possible then to add a line in the end that deletes the file? I'll try it out..
#
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.
#
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
#
For get it work with south migrations I had to changed some lines...
And adding the specific rule for south and the end of the file
#
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"])
#
oops! i forgot the slashes!!
#
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/
#
@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.
#
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?
#
A new & dusted off version, checking minimum size, maximum size, matching extensions and mime types.
https://gist.github.com/1183767
#
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.
#