Django Image Upload ...防止大量文件上传

时间:2011-04-24 00:19:02

标签: django file django-models file-upload

我的网站依赖于用户上传的图片文件。我想限制max_upload_size。

我知道您可以在settings.py中设置FILE_UPLOAD_MAX_MEMORY_SIZE。如果上载的文件大于此大小,则会将其写入tmp目录中的磁盘。这几乎可以解决问题吗?巨大的图像是否会影响我网站的性能?

我见过的一个替代方案是在apache中配置max_upload_size,它(似乎)包含在php.ini中。听起来不错吗?这是可取的吗?

另一步涉及检查文件对象的属性。我查看了这个snipet(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,即使它引发验证错误?

最后,您还会注意到此表单验证会尝试过滤内容类型。我认为这几乎毫无价值,因为它只是在看扩展,这很容易被欺骗。那也公平吗?

我知道这个问题有点夸张,但这是一个艰难而且难以扩散的主题(至少对我而言)

2 个答案:

答案 0 :(得分:4)

  

我知道你可以设置   FILE_UPLOAD_MAX_MEMORY_SIZE in   settings.py。如果文件大于   此大小已上传,已写入   tmp目录中的磁盘。那样做   几乎处理的事情?会巨大的   图像仍会影响我的网站   表现完全?

取决于“句柄”的含义。它将使处理上传的进程不会将整个文件读入内存并耗尽服务器的资源。它仍然会成功上传,你仍然会保存一个“大”文件。我认为它可能会影响您网站的性能,因为您要将服务器进程与上传相关联,因为上传需要更长的时间才会完成,因为它会打到相对较慢的磁盘。

  

我见过的另一种选择是   在中配置max_upload_size   apache,它似乎被包含了   在php.ini中。听起来不错吗?是   这是可取的吗?

有一种方法可以在apache中限制请求的大小,但不是通过该设置。 php.ini中的任何内容都特定于PHP,与Django无关。你正在寻找apache的LimitRequestBody指令。

这里的问题是关于你想要完成的事情。您是否只想限制网站存储的文件大小,但您不关心它们是否实际上传(您不关心带宽使用情况)?如果是这样,那么您可以使用表单验证路径,以便为您的用户提供更好的错误。

但是,如果您确实关心大型上传所使用的带宽,并且您希望停止以N MB上传任何文件,那么您应该考虑使用类似QuotaUploadHandler的内容或通过您设置限制webserver(参见上面的LimitRequestBody)。如果你使用上传处理程序,你需要在引发StopUpload异常时测试行为 - 在File Uploads文档的“receive_data_chunk”方法中有一个关于它的微小评论。如果您选择让apache在一定大小后停止上传,您可能最终会向超出该限制的用户显示一些相当丑陋的错误页面。

答案 1 :(得分:1)

尝试以下代码,

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')
相关问题