簡體   English   中英

在Django中按內容類型驗證文件的更好方法

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

因此,我實現了以下托管的代碼段:

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

到目前為止,這是我的代碼:

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

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

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')

據我了解,這種方法仍然可以通過修改標頭輕松地覆蓋。 我要問的是,對於這種情況是否有更好的方法?

為了驗證客戶端給定的文件內容是否匹配給定的內容類型,您需要一個完整的數據庫來描述如何檢測內容類型。

但是,您可以依賴libmagic項目。 在pypi上有此庫的綁定: python-magic

您需要調整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

編寫這段代碼是為了演示其工作原理,而不是在減少冗余代碼的情況下。

我不建議您在生產代碼中獨自執行此操作。 我建議使用已經存在的代碼。 如果您真的只需要驗證圖像已上傳並可以查看,則建議使用ImageField表單字段。 請注意,ImageField使用枕頭來確保可以打開圖像。 這可能會或可能不會對您的服務器構成威脅。

還有其他幾個可用的項目,它們完全實現了確保已上傳某種內容類型的文件的所需功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM