简体   繁体   English

在Django中按内容类型验证文件的更好方法

[英]Better Way to validate file by content-type in django

So i have implement the snippet hosted below: 因此,我实现了以下托管的代码段:

https://djangosnippets.org/snippets/1303/ https://djangosnippets.org/snippets/1303/

here is my code so far: 到目前为止,这是我的代码:

models.py models.py

class Vehicle(models.Model):
    pub_date = models.DateTimeField('Date Published', auto_now_add=True)
    make = models.CharField(max_length=200)
    model = models.CharField(max_length=200)
    picture = models.FileField(upload_to='picture')

    def __unicode__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('recipe_edit', kwargs={'pk': self.pk})

views.py views.py

def vehicle_list(request, template_name='vehicle/vehicle_list.html'):
    if request.POST:
        form = VehicleForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            return redirect('vehicle_list')
    else:
        form = VehicleForm()  # Create empty form

    vehicles = Vehicle.objects.all()  # Retrieve all vehicles from DB
    return render(request, template_name, {
        'vehicles': vehicles,
        'form': form
    },context_instance=RequestContext(request))

forms.py forms.py

class VehicleForm(forms.ModelForm):
    class Meta:
        model = Vehicle

    def clean_picture(self):
        content = self.cleaned_data['picture']
        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 file size under %s', filesizeformat(content.size))
        else:
            raise forms.ValidationError('File type is not supported')

From what i understand, this approach can still easily overridden by modifying the header. 据我了解,这种方法仍然可以通过修改标头轻松地覆盖。 What i am asking is, whether there is a better approach for this situation? 我要问的是,对于这种情况是否有更好的方法?

In order to verify that the given file content matches the given content type by the client you need a full fledged database which describes how the content type can be detected. 为了验证客户端给定的文件内容是否匹配给定的内容类型,您需要一个完整的数据库来描述如何检测内容类型。

You can rely on the libmagic project instead though. 但是,您可以依赖libmagic项目。 There are bindings for this library available on the pypi: python-magic 在pypi上有此库的绑定: python-magic

You need to adjust your VehicleForm so that it does the content type detection: 您需要调整VehicleForm以便进行内容类型检测:

class VehicleForm(forms.ModelForm):

    class Meta(object):
        model = Vehicle

    def clean_picture(self):
        content = self.cleaned_data['picture']
        try:
            content.open()
            # read only a small chunk or a large file could nuke the server
            file_content_type = magic.from_buffer(content.read(32768),
                                                  mime=True)
        finally:
            content.close()

        client_content_root_type = content.content_type.split('/')[0]
        file_content_root_type = file_content_type.split('/')[0]

        if client_content_root_type in settings.CONTENT_TYPES and \
                file_content_root_type in settings.CONTENT_TYPES:
            if content.size > settings.MAX_UPLOAD_SIZE:
                raise forms.ValidationError('Please keep file size under %s',
                                            filesizeformat(content.size))
        else:
            raise forms.ValidationError('File type is not supported')
        return content

This chunk of code was written to show how it works, not with reducing redundant code in mind. 编写这段代码是为了演示其工作原理,而不是在减少冗余代码的情况下。

I wouldn't recommend doing this by yourself in production Code. 我不建议您在生产代码中独自执行此操作。 I would recommend using already present code. 我建议使用已经存在的代码。 I would recommend the ImageField form field if you really only need to verify that an image has been uploaded and can be viewed. 如果您真的只需要验证图像已上传并可以查看,则建议使用ImageField表单字段。 Please notice that the ImageField uses Pillow to ensure that the image can be opened. 请注意,ImageField使用枕头来确保可以打开图像。 This might or might not pose a threat to your server. 这可能会或可能不会对您的服务器构成威胁。

There are also several other projects available which exactly implements the desired feature of ensuring that a file of a certain content type has been uploaded. 还有其他几个可用的项目,它们完全实现了确保已上传某种内容类型的文件的所需功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM