我的网站依赖于用户上传的图像文件。我想限制max_upload_size。
我知道你可以在settings.py中设置FILE_UPLOAD_MAX_MEMORY_SIZE。如果上传的文件大于这个大小,则会将其写入tmp目录下的磁盘。这样就能解决问题了吗?巨大的图片还会影响网站的性能吗?
我看到的另一种选择是在apache中配置max_upload_size,它(似乎)包含在php.ini中。听起来对吗?这样合适吗?
另一个步骤涉及检查File Object的属性。我已经浏览了这个代码片段(http://djangosnippets.org/snippets/1303/),它提供了一个表单验证方法。
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
这里潜在的问题是
1)这段代码适用于FileField,而不是ImageField。我知道ImageField子类FileField,所以我认为这不是问题。这是真的吗?
2)在验证之前读取整个HttpRequest请求(所以巨大的文件仍然是一个问题)。另外,文件是否仍然写入tmp,即使它引发验证错误?
最后,您还会注意到这个表单验证尝试过滤内容类型。我认为这基本上是没有价值的,因为它只是在查看扩展,很容易被欺骗。这也公平吗?
我知道这个问题有点漫无目的,但这是一个艰难而广泛的主题(至少对我来说)
我知道你可以设置FILE_UPLOAD_MAX_MEMORY_SIZE在settings.py。如果文件大于这个大小被上传,它被写入TMP目录下的磁盘。这差不多搞定事情了吧?将巨大的图片仍然影响着我的网站性能?
取决于你所说的"handle"是什么意思。它将防止处理上载的进程将整个文件读取到内存中并耗尽服务器的资源。它仍然会成功上传,你仍然会保存一个"大"文件。我认为这可能会影响你网站的性能,因为你要保持一个服务器进程与一个上传绑定,这将需要更长的时间来完成,因为它将到达磁盘,这是相对较慢的。
我看到的另一种选择是配置max_upload_sizeApache,它(看起来)包含在php . ini中。听起来对吗?是明智的吗?
在apache中有一种限制请求大小的方法,但它不是通过设置。PHP .ini中的任何内容都是特定于PHP的,与Django无关。你正在寻找apache的LimitRequestBody指令。
这里的问题是关于你想要完成什么。您是否只想限制站点存储的文件的大小,而不关心它们是否被上载(您不关心您的带宽使用情况)?如果是这样,那么您可以使用表单验证路由,以便向用户呈现更好的错误。
然而,如果你确实关心大上传所使用的带宽,并且你想停止上传任何文件在N MB,那么你应该考虑使用类似QuotaUploadHandler的东西或通过你的web服务器设置一个限制(参见上面的LimitRequestBody)。如果使用上载处理程序,则需要在引发StopUpload异常时测试其行为——在File Uploads文档中的"receive_data_chunk"方法中有一个关于它的小注释。如果您选择让apache在超过一定大小后停止上传,那么您可能最终会向超过该限制的用户显示一些相当难看的错误页面。
试试下面的代码,
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')