Reputation: 16610
My site relies on user uploaded image files. I want to limit the max_upload_size.
I know that you can set FILE_UPLOAD_MAX_MEMORY_SIZE in settings.py. If a file larger than this size is uploaded, it's written to the disk within the tmp dir. Does that pretty much handle things? Will huge images still affect my site's performance at all?
One alternative that I've seen is to configure the max_upload_size in apache, which (it seems) is contained in php.ini. Does that sound right? Is it advisable?
Another step involves inspecting the File Object's attributes. I've looked through this snipet (http://djangosnippets.org/snippets/1303/) which presents a form validation method.
def clean_content(self):
content = self.cleaned_data['content']
content_type = content.content_type.split('/')[0]
if content_type in settings.CONTENT_TYPES:
if content._size > settings.MAX_UPLOAD_SIZE:
raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(settings.MAX_UPLOAD_SIZE), filesizeformat(content._size)))
else:
raise forms.ValidationError(_('File type is not supported'))
return content
The potential issues here are that
1) this code applies to a FileField, not an ImageField. I know that ImageField subclasses FileField, so I assume that this is not an issue. Is that true?
2)The entire HttpRequest request is read before validation (so huge files would still be a problem). Also, is the file still written to tmp, even if it raises a validation error?
Finally, you'll also notice that this form validation attempts to filter for content types. I assume that's mostly worthless as it's just looking at extensions, which can easily be spoofed. Is that also fair?
I know this question is a bit rambling, but it's a tough and diffusive subject matter (for me at least)
Upvotes: 1
Views: 2947
Reputation: 6594
I know that you can set FILE_UPLOAD_MAX_MEMORY_SIZE in settings.py. If a file larger than this size is uploaded, it's written to the disk within the tmp dir. Does that pretty much handle things? Will huge images still affect my site's performance at all?
Depends on what you mean by "handle". It will keep the process handling the upload from reading the entire file into memory and using up your server's resources. It will still succeed in uploading and you'll still be saving a "large" file. I would think it could affect your site's performance because you're going to keep a server process tied up with an upload that will take longer to complete since it is going to hit the disk, which is relatively slow.
One alternative that I've seen is to configure the max_upload_size in apache, which (it seems) is contained in php.ini. Does that sound right? Is it advisable?
There is a way to limit a request's size in apache but it's not via that setting. Anything in php.ini is specific to PHP and irrelevant to Django. You're looking for apache's LimitRequestBody directive.
The question here is about what you want to accomplish. Do you only want to limit the size of the files your site stores, but you do not care if they are actually uploaded (you're not concerned about your bandwidth usage)? If so, then you can go the form validation route so as to present nicer errors to your users.
However, if you do care about the bandwidth used by large uploads and you want to stop the upload of any file at N MB, then you should look into using something like this QuotaUploadHandler or setting a limit via your webserver (see LimitRequestBody above). If you use the upload handler, you'll need to test the behavior when the StopUpload exception is raised -- there is a tiny comment about it in the "receive_data_chunk" method in the File Uploads docs. If you choose to let apache stop uploads after a certain size, you'll probably end up showing some rather ugly error pages to your users who surpass that limit.
Upvotes: 4
Reputation: 5424
Try below code,
from django.core.exceptions import ValidationError
def validate_image(fieldfile_obj):
filesize = fieldfile_obj.file.size
megabyte_limit = 2.0
if filesize > megabyte_limit*1024*1024:
raise ValidationError("Max file size is %sMB" % str(megabyte_limit))
class User(models.Model):
avatar = models.ImageField("Avatar", upload_to=upload_logo_to,validators=[validate_image], blank=True, null=True,help_text='Maximum file size allowed is 2Mb')
Upvotes: 1