6

我需要验证上传文件的文件类型,并且应该只允许 pdf、plain test 和 MS word 文件。这是我的模型和具有验证功能的表单。但是,即使没有扩展名,我也可以上传文件。

class Section(models.Model):
    content = models.FileField(upload_to="documents")

class SectionForm(forms.ModelForm):
    class Meta:
        model = Section
    FILE_EXT_WHITELIST = ['pdf','text','msword']

    def clean_content(self):
        content = self.cleaned_data['content']
        if content:
            file_type = content.content_type.split('/')[0]
            print file_type
            if len(content.name.split('.')) == 1:
                raise forms.ValidationError("File type is not supported.")
            if content.name.split('.')[-1] in self.FILE_EXT_WHITELIST:
                return content
            else:
                raise forms.ValidationError("Only '.txt' and '.pdf' files are allowed.")

这里的景色,

def section_update(request, object_id):
    section = models.Section.objects.get(pk=object_id)
    if 'content' in request.FILES:
            if request.FILES['content'].name.split('.')[-1] == "pdf":
                content_file = ContentFile(request.FILES['content'].read())
                content_type = "pdf"
                section.content.save("test"+'.'+content_type , content_file)
                section.save()

在我看来,我只是将文件从request.FILE. 我认为在 save() 时它会调用 clean_content 并进行内容类型验证。我想, clean_content 根本不需要验证。

4

3 回答 3

5

您的方法将不起作用:作为攻击者,我可以简单地伪造 HTML 标头向您发送任何具有 mime 类型的内容text/plain

正确的解决方案是使用file(1)Unix 上的工具来检查文件的内容以确定它是什么。请注意,没有什么好方法可以知道某些内容是否真的是纯文本。如果文件以 16 位 Unicode 保存,“纯文本”甚至可以包含 0 个字节。

有关如何执行此操作的选项,请参阅此问题:How to find the mime type of a file in python?

于 2012-08-02T08:22:12.600 回答
2

你可以使用python-magic

import magic
magic.from_file('/my/file.jpg', mime=True)
# image/jpeg
于 2019-01-06T12:58:44.853 回答
0

这是一个老问题,但对于后来的用户来说,评论中提到的主要问题是为什么没有发生字段验证,并且如 django 文档中所述,当您调用 is_valid() 时执行字段验证。所以必须使用下面的东西来激活字段验证:

section = models.Section.objects.get(pk=object_id)    
if request.method == 'POST':    
   form = SectionForm(request.POST, request.FILES)
   if form.is_valid:
      do_something_with_form

清理数据时会进行表单验证。如果您想自定义此过程,可以在多个地方进行更改,每个地方都有不同的用途。在表格处理期间运行三种类型的清洁方法。这些通常在您在表单上调用 is_valid() 方法时执行

于 2021-04-15T14:12:28.507 回答