Python:检查上传的文件是否为jpg

时间:2022-09-13 14:00:20

How can I check if a file uploaded by a user is a real jpg file in Python (Google App Engine)?

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

This is how far I got by now:

这是我现在走了多远:

Script receives image via HTML Form Post and is processed by the following code

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

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

I found mimetypes.guess_type, but it does not work for me.

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

5 个解决方案

#1


36  

If you need more than looking at extension, one way would be to read the JPEG header, and check that it matches valid data. The format for this is:

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

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

so a quick recogniser would be:

所以一个快速识别器将是:

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

However this won't catch any bad data in the body. If you want a more robust check, you could try loading it with PIL. eg:

然而,这不会捕获身体中的任何不良数据。如果您想要更强大的检查,可以尝试使用PIL加载它。例如:

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

#2


33  

No need to use and install the PIL lybrary for this, there is the imghdr standard module exactly fited for this sort of usage.

不需要为此使用和安装PIL lybrary,imghdr标准模块完全适合这种用法。

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

import imghdr

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

As you have an image from a stream you may use the stream option probably like this :

由于您拥有流中的图像,因此您可以使用stream选项,如下所示:

image_type = imghdr.what(filename, incomming_image)

Actualy this works for me in Pylons (even if i have not finished everything) : in the Mako template :

Actualy这适用于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()}

in the upload controler :

在上传控制器中:

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

#3


1  

A more general solution is to use the Python binding to the Unix "file" command. For this, install the package python-magic. Example:

更通用的解决方案是使用Python绑定到Unix“file”命令。为此,安装包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()

#4


0  

Use PIL. If it can open the file, it's an image.

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

From the tutorial...

从教程......

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

#5


0  

The last byte of the JPEG file specification seems to vary beyond just e0. Capturing the first three is 'good enough' of a heuristic signature to reliably identify whether the file is a jpeg. Please see below modified proposal:

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

#1


36  

If you need more than looking at extension, one way would be to read the JPEG header, and check that it matches valid data. The format for this is:

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

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

so a quick recogniser would be:

所以一个快速识别器将是:

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

However this won't catch any bad data in the body. If you want a more robust check, you could try loading it with PIL. eg:

然而,这不会捕获身体中的任何不良数据。如果您想要更强大的检查,可以尝试使用PIL加载它。例如:

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

#2


33  

No need to use and install the PIL lybrary for this, there is the imghdr standard module exactly fited for this sort of usage.

不需要为此使用和安装PIL lybrary,imghdr标准模块完全适合这种用法。

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

import imghdr

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

As you have an image from a stream you may use the stream option probably like this :

由于您拥有流中的图像,因此您可以使用stream选项,如下所示:

image_type = imghdr.what(filename, incomming_image)

Actualy this works for me in Pylons (even if i have not finished everything) : in the Mako template :

Actualy这适用于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()}

in the upload controler :

在上传控制器中:

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

#3


1  

A more general solution is to use the Python binding to the Unix "file" command. For this, install the package python-magic. Example:

更通用的解决方案是使用Python绑定到Unix“file”命令。为此,安装包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()

#4


0  

Use PIL. If it can open the file, it's an image.

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

From the tutorial...

从教程......

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

#5


0  

The last byte of the JPEG file specification seems to vary beyond just e0. Capturing the first three is 'good enough' of a heuristic signature to reliably identify whether the file is a jpeg. Please see below modified proposal:

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