使用django形式检查文件类型:' application / octet-stream'问题

时间:2015-02-12 09:20:49

标签: python django django-forms mime-types

我正在使用django验证器和python-magic来检查上传文档的mime类型,并且只接受pdf,zip和rar文件。

接受的mime类型是: “应用程序/ PDF”, 'application / zip','multipart / x-zip','application / x-zip-compressed','application / x-compressed',  'application / rar','application / x-rar''application / x-rar-compressed','compressed / rar',

问题在于,有时pdf文件似乎将'application / octet-stream'作为mime-type。 'application / octet-stream'表示通用二进制文件,所以我不能简单地将mime类型添加到接受文件列表中,因为在这种情况下也会接受其他文件,例如es excel文件,我不想要那会发生。

在这种情况下我该怎么做?

提前致谢。

3 个答案:

答案 0 :(得分:0)

您不应该依赖提供的MIME类型,而应该依赖于从文件本身的前几个字节中发现的MIME类型。

这有助于消除通用的MIME类型问题。

这种方法的问题在于它通常依赖于某些第三方工具(例如Linux系统中常见的file命令很棒;与-b --mime -一起使用并传入第一个你文件的几个字节让它给你mime类型。)

您拥有的另一个选择是接受该文件,并尝试通过使用库打开它来验证它。

因此,如果pypdf无法打开文件,并且内置的zip模块无法打开文件,并且rarfile无法打开文件 - 最有可能是您不知道的事情# 39;我想接受。

答案 1 :(得分:0)

最简单的说法是通过在文件头中读取元数据来窥探文件内容。

在大多数文件中,此文件标题通常存储在文件的开头,但在某些文件中,它可能位于其他位置。

python-magic可以帮助你做到这一点,但诀窍是在尝试猜测其mime类型之前始终将指针重置在文件的开头,否则你有时会得到appliation / octet-stream mime如果读者的指针已超过文件头位置,则输入到只包含任意字节流的其他位置。

例如,如果你有一个django验证器函数试图验证mime类型的上传文件:

import magic
from django.core.exceptions import ValidationError

def validate_file_type(upload):
    allowed_filetypes = [
        'application/pdf', 'image/jpeg', 'image/jpg', 'image/png',
        'application/msword']
    upload.seek(0)
    file_type = magic.from_buffer(upload.read(1024), mime=True)
    if file_type not in allowed_filetypes:
        raise ValidationError(
            'Unsupported file')

答案 2 :(得分:0)

作为对Liyosi答案的跟进,我还使用了python-magic。 libmagic似乎存在一个错误,它仍然错误地将某些文件标识为application/octet-streamcode

上有更好的描述
    def _handle509Bug(self, e):
        # libmagic 5.09 has a bug where it might fail to identify the
        # mimetype of a file and returns null from magic_file (and
        # likely _buffer), but also does not return an error message.
        if e.message is None and (self.flags & MAGIC_MIME):
            return "application/octet-stream"
        else:
            raise e

要解决此问题,我必须实例化一个魔术对象并使用uncompressedmime属性。要完成Liyosi示例,请执行以下操作:

import magic
from django.core.exceptions import ValidationError

def validate_file_type(upload):
    allowed_filetypes = [
        'application/pdf', 'image/jpeg', 'image/jpg', 'image/png',
        'application/msword']
    validator = magic.Magic(uncompress=True, mime=True)
    file_type = validator.from_buffer(upload.read(), mime=True)
    if file_type not in allowed_filetypes:
        raise ValidationError('Unsupported file')