【问题标题】:Checking file type with django form: 'application/octet-stream' issue使用 django 形式检查文件类型:'application/octet-stream' 问题
【发布时间】:2015-04-12 23:03:54
【问题描述】:

我正在使用 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 文件似乎将“应用程序/八位字节流”作为 mime 类型。 'application/octet-stream' 表示通用二进制文件,所以我不能简单地将该 mime 类型添加到接受的文件列表中,因为在这种情况下,也会接受其他文件,例如 es excel 文件,我不想要那会发生。

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

提前致谢。

【问题讨论】:

    标签: python django django-forms mime-types


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 这仍然会为 appliation/octet-stream 提供某些文件
      【解决方案3】:

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

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

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

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

      因此,如果pypdf 无法打开文件,而内置的zip 模块无法打开文件,而rarfile 无法打开文件 - 这很可能是您不想接受的情况。

      【讨论】:

      • 我不依赖提供的 MIME 类型。我已经阅读了前几个字节来发现它,使用 python-magic: mime = magic.from_buffer(value.read(1024), mime=True) 但这种方法有时也会给出“application/octet-stream”
      • 选择第二个选项。
      猜你喜欢
      • 2015-04-12
      • 2019-10-16
      • 2011-11-21
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 2021-11-15
      • 2014-06-08
      相关资源
      最近更新 更多