【问题标题】:Python: Check if uploaded file is jpgPython:检查上传的文件是否为jpg
【发布时间】:2010-09-20 23:11:53
【问题描述】:

如何在 Python (Google App Engine) 中检查用户上传的文件是否为真正的 jpg 文件?

这是我现在的进度:

脚本通过 HTML Form Post 接收图像并由以下代码处理

...
incomming_image = self.request.get("img")
image = db.Blob(incomming_image)
...

我找到了 mimetypes.guess_type,但它对我不起作用。

【问题讨论】:

    标签: python google-app-engine image image-processing mime


    【解决方案1】:

    JPEG 文件规范的最后一个字节似乎不仅仅是 e0。捕获前三个是启发式签名的“足够好”,可以可靠地识别文件是否为 jpeg。请参阅以下修改后的提案:

    def is_jpg(filename):
        data = open("uploads/" + filename,'rb').read(11)
        if (data[:3] == "\xff\xd8\xff"):
            return True
        elif (data[6:] == 'JFIF\0'): 
            return True
        else:
            return False
    

    【讨论】:

      【解决方案2】:

      更通用的解决方案是使用 Python 绑定到 Unix“文件”命令。为此,请安装包 python-magic。示例:

      import magic
      
      ms = magic.open(magic.MAGIC_NONE)
      ms.load()
      type =  ms.file("/path/to/some/file")
      print type
      
      f = file("/path/to/some/file", "r")
      buffer = f.read(4096)
      f.close()
      
      type = ms.buffer(buffer)
      print type
      
      ms.close()
      

      【讨论】:

        【解决方案3】:

        无需为此使用和安装 PIL 库,imghdr 标准模块正好适合这种用途。

        http://docs.python.org/library/imghdr.html

        import imghdr
        
        image_type = imghdr.what(filename)
        if not image_type:
            print "error"
        else:
            print image_type
        

        当您有来自流的图像时,您可能会像这样使用流选项:

        image_type = imghdr.what(filename, incomming_image)
        

        实际上,这在 Pylons 中对我有用(即使我还没有完成所有事情): 在 Mako 模板中:

        ${h.form(h.url_for(action="save_image"), multipart=True)}
        Upload file: ${h.file("upload_file")} <br />
        ${h.submit("Submit", "Submit")}
        ${h.end_form()}
        

        在上传控制器中:

        def save_image(self):
            upload_file = request.POST["upload_file"]
            image_type = imghdr.what(upload_file.filename, upload_file.value)
            if not image_type:
                return "error"
            else:
                return image_type
        

        【讨论】:

          【解决方案4】:

          如果您需要的不仅仅是查看扩展名,一种方法是读取 JPEG 标头,并检查它是否与有效数据匹配。其格式为:

          Start Marker  | JFIF Marker | Header Length | Identifier
          0xff, 0xd8    | 0xff, 0xe0  |    2-bytes    | "JFIF\0"
          

          所以快速识别器是:

          def is_jpg(filename):
              data = open(filename,'rb').read(11)
              if data[:4] != '\xff\xd8\xff\xe0': return False
              if data[6:] != 'JFIF\0': return False
              return True
          

          但是,这不会捕获正文中的任何不良数据。如果您想要更可靠的检查,可以尝试使用PIL 加载它。例如:

          from PIL import Image
          def is_jpg(filename):
              try:
                  i=Image.open(filename)
                  return i.format =='JPEG'
              except IOError:
                  return False
          

          【讨论】:

          • 第四个字节并不总是0xe0,0xe1也很常见,相信还有其他可能。
          【解决方案5】:

          使用PIL。如果它可以打开文件,那就是图像。

          从教程...

          >>> import Image
          >>> im = Image.open("lena.ppm")
          >>> print im.format, im.size, im.mode
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-29
          • 1970-01-01
          • 2011-10-03
          • 1970-01-01
          • 2017-06-11
          相关资源
          最近更新 更多