如何检查用户上传的文件是否是 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)中的真实 jpg 文件?
这是我现在走了多远:
脚本通过 HTML Form Post 接收图像并由以下代码处理
...
incomming_image = self.request.get("img")
image = db.Blob(incomming_image)
...
我找到了 mimetypes.guess_type,但它对我不起作用。
如果您需要的不仅仅是查看扩展名,一种方法是读取 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
无需为此使用和安装 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
更通用的解决方案是使用 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()
使用PIL。如果它可以打开文件,那就是图像。
从教程...
>>> import Image
>>> im = Image.open("lena.ppm")
>>> print im.format, im.size, im.mode
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