【问题标题】:How to find file extension of base64 encoded image in Python如何在 Python 中查找 base64 编码图像的文件扩展名
【发布时间】:2014-01-28 19:53:53
【问题描述】:

我有一个 base64 编码的图像,我将其解码并保存到 Django 中的 ImageField 中。我想给文件一个随机的名字,但我不知道文件扩展名。

我在字符串前面添加了“data:image/png;base64”,我知道我可以做一些正则表达式来提取 mimetype,但我想知道是否有最佳实践方法可以从“ data:image/png;base64," 可靠地转换为 ".png"。当有人突然想上传我不支持的奇怪图像文件类型时,我不想让我的手动功能中断。

【问题讨论】:

标签: python image base64 mime-types file-extension


【解决方案1】:

假设 base64 编码在变量 encoded_string 中,下面的代码适用于我:

from base64 import b64decode
import imghdr

encoded_string = 'image base64 encoded'

decoded_string = b64decode(encoded_string)
extension = imghdr.what(None, h=decoded_string)

【讨论】:

    【解决方案2】:

    我在 Lambda 中编写了代码,它将查找图像的类型并检查 base64 是否为图像。

    以下代码肯定会对某人有所帮助。

    import base64
    import imghdr
    def lambda_handler(event, context):
        image_data = event['img64']    # crate "json event" in lambda 
                                       # Sample JSON Event ========>  { "img64" : BASE64 of an Image }
                                       # Get BASE64 Data of image in image_data variable.
        sample = base64.b64decode(image_data)      # Decode the base64 data and assing to sample.
    
        for tf in imghdr.tests:
            res = tf(sample, None)
            if res:
                break;
        print("Extension OR Type of the Image =====>",res)
        if(res==None): # if res is None then BASE64 is of not an image.
                return {
                'status': 'False',
               'statusCode': 400,
               'message': 'It is not image, Only images allowed'
              }
        else:
            return 'It is image'  
    

    注意:- 以上代码是用python编写的Lambda(AWS),您可以将以下代码复制并粘贴到您的本地机器上并进行如下测试。

    import base64
    import imghdr
    image_data = "BASE64 OF AN IMAGE"
    sample = base64.b64decode(image_data)      # Decode the base64 data and     assing to sample.
    
    for tf in imghdr.tests:
        res = tf(sample, None)
        if res:
            break;
    print("Extension OR Type of the Image =====>",res)
    if(res==None):
        print('It is not image, Only images allowed')
    else:
        print('It is image')
    

    【讨论】:

      【解决方案3】:

      看起来mimetypes stdlib module 即使在 Python 2 中也支持数据 url:

      >>> from mimetypes import guess_extension, guess_type
      >>> guess_extension(guess_type("data:image/png;base64,")[0])
      '.png'
      

      【讨论】:

      • 它为 'image/jpeg' 返回 '.jpe' =(
      【解决方案4】:

      最好检查文件的内容,而不是依赖文件外部的内容。例如,许多电子邮件攻击依赖于错误识别 mime 类型,以便毫无戒心的计算机执行它不应该执行的文件。幸运的是,大多数图像文件扩展名可以通过查看前几个字节来确定(解码 base64 之后)。不过,最佳实践可能是使用file magic,它可以通过this onethis one 等python 包访问。

      从 mimetype 中可以看出大多数图像文件的扩展名。对于 gif、pxc、png、tiff 和 jpeg,文件扩展名就是 mime 类型的“image/”部分之后的任何内容。为了处理晦涩的类型,python 确实提供了一个标准包:

      >>> from mimetypes import guess_extension
      >>> guess_extension('image/x-corelphotopaint')
      '.cpt'
      >>> guess_extension('image/png')
      '.png'
      

      【讨论】:

      • mimetype 已经存在 - 使用 libmagic 只会找到 mimetype,而不是建议扩展。
      • 您是否建议通过filemagic 获取mime 类型比直接使用提供的mime 类型更安全?
      • @J.F.Sebastian 根据我的经验,即使是非恶意电子邮件,提供的许多文件类型也是错误的。提供的 mime 类型可能只是文件扩展名的表格查找。
      • Libmagic 显然是确定 mime 类型的最安全方法,但它并不总是足以确定扩展名(正如问题现在所述)。使用 mime 子类型作为文件扩展名的一个危险是,某些(模糊的)mime 类型包含不能用于 FAT 文件名的+,因此会在某些系统上产生错误。
      • @Graeme 这是个好主意。为了获取更多数据,我刚刚做了grep '+' /etc/mime.types,发现了两个带有加号的扩展,都与c++源代码有关。更广泛的搜索[ ext for ext in mimetypes.types_map if '+' in ext ] 产生了相同的结果。另外,在查看grep image /etc/mime.types 之后,我发现建议的扩展中没有非ASCII 字符。
      【解决方案5】:

      您可以使用 mimetypes 模块 - http://docs.python.org/2/library/mimetypes.html

      基本上mimetypes.guess_extension(mine) 应该可以完成这项工作。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多