在Django中验证上传文件类型

时间:2017-07-18 16:26:40

标签: python django

我有一个带有文件字段的Post模型,用于上传文件。如何验证文件类型(目前为pdf,如果我稍后更改,则为任何其他类型)。我最好是要验证内容,但如果没有,我猜后缀也会这样做。我试着在网上查询,但我找到的大多数解决方案都是从后面回来的,随着Django文档的更新,他们不再工作了。请有人帮忙。感谢。

class Post(models.Model):
    author = models.ForeignKey('auth.User',default='')
    title = models.CharField(max_length=200)
    text = models.TextField()
    PDF = models.FileField(null=True, blank=True)
    created_date = models.DateTimeField(
            default=timezone.now)
    published_date = models.DateTimeField(
            blank=True, null=True)

    def publish(self):
        self.published_date = timezone.now()
        self.save()

    def __str__(self):
        return self.title

4 个答案:

答案 0 :(得分:5)

使用Django 1.11,您可以使用FileExtensionValidator。对于早期版本或额外验证,您可以基于它构建自己的验证器。你应该以这种方式创建一个验证器:

  

不要依赖文件扩展名的验证来确定文件的类型。无论文件包含哪些数据,都可以重命名文件以获得任何扩展名。

这是一个包含现有验证器的示例代码:

from django.core.validators import FileExtensionValidator
class Post(models.Model):
    PDF = models.FileField(null=True, blank=True, validators=[FileExtensionValidator(['pdf'])])

源代码也可用,因此您可以轻松创建自己的代码:

https://docs.djangoproject.com/en/1.11/_modules/django/core/validators/#FileExtensionValidator

答案 1 :(得分:1)

根据以下方面考虑验证:

  • 名称/延伸
  • 元数据(内容类型,大小)
  • 实际内容(内容类型是真的是PNG,还是恶意PDF?)

前两个主要是化妆品 - 很容易欺骗/伪造这些信息。通过添加内容验证(通过文件魔术 - https://pypi.python.org/pypi/filemagic),您可以添加一些额外的保护

这是一个很好的相关答案:Django: Validate file type of uploaded file它可能很旧,但核心思想应该很容易适应。

答案 2 :(得分:0)

首先,我建议你将'PDF'改为'pdf',然后 要在旧版本的Django中验证,你可以这样做

<强> forms.py

class PostForm(forms.ModelForm):
    # fields here
    class Meta:
        model = Post
        fields = ["title", "text", "pdf"]

    def clean(self):
        cd = self.cleaned_data
        pdf = cd.get('pdf', None)
        if pdf is not None:
            main, sub = pdf.content_type.split('/')
            # main here would most likely be application, as pdf mime type is application/pdf, 
            # but I'd like to be on a safer side should in case it returns octet-stream/pdf
            if not (main in ["application", "octet-stream"] and sub == "pdf"):
                raise forms.ValidationError(u'Please use a PDF file')
         return cd

答案 3 :(得分:0)

以下是基于Django 1.11 FileExtensionValidator的文件类型验证表单的简单示例

class ImageForm(ModelForm):
    ALLOWED_TYPES = ['jpg', 'jpeg', 'png', 'gif']

    class Meta:
        model = Profile
        fields = ['image', ]

    def clean_avatar(self):
        image = self.cleaned_data.get('image', None)
        if not avatar:
            raise forms.ValidationError('Missing image file')
        try:
            extension = os.path.splitext(image.name)[1][1:].lower()
            if extension in self.ALLOWED_TYPES:
                return avatar
            else:
                raise forms.ValidationError('File types is not allowed')
        except Exception as e:
            raise forms.ValidationError('Can not identify file type')