2008-11-05 25 views
15

¿Cómo puedo comprobar si un archivo cargado por un usuario es un archivo jpg real en Python (Google App Engine)?Python: compruebe si el archivo cargado es jpg

Esto es lo lejos que tengo por ahora:

script recibe la imagen a través de formularios HTML Post y es procesado por el siguiente código

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

encontré mimetypes.guess_type, pero no funciona para yo.

Respuesta

36

Si necesita algo más que mirar la extensión, una forma sería leer el encabezado JPEG y verificar que coincida con los datos válidos. El formato de este es:

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

así habría un reconocedor rápida:

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 

Sin embargo, esto no va a coger los datos dañados en el cuerpo. Si desea un control más robusto, puede intentar cargarlo con PIL. por ejemplo:

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

Use PIL. Si puede abrir el archivo, es una imagen.

Desde el tutorial ...

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

Esto no funcionará en App Engine: PIL contiene código C y, por lo tanto, no está disponible. La API de imágenes (http://code.google.com/appengine/docs/images/) usa PIL, pero está apagada. – chryss

33

No hay necesidad de usar e instalar la Lybrary PIL para esto, existe el módulo estándar imghdr fited exactamente para este tipo de uso.

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

import imghdr 

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

Como usted tiene una imagen de una corriente que puede utilizar la opción de corriente, probablemente como esto:

image_type = imghdr.what(filename, incomming_image) 

podía comprender esto funciona para mí en los pilones (incluso si no he terminado todo): en la plantilla de 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()} 

en la controladora de carga:

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 para que imghdr sea un módulo estándar –

+1

Para archivos .jpg 'imghdr.what()' devuelve 'None'. – Rico

1

Una solución más general es utilizar el enlace de Python para el comando Unix "archivo". Para esto, instala el paquete python-magic. Ejemplo:

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() 
0

El último byte de la especificación del archivo JPEG parece variar más allá de e0. La captura de los tres primeros es 'suficientemente buena' de una firma heurística para identificar de manera confiable si el archivo es un jpeg. Consulte a continuación la propuesta modificada:

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 
Cuestiones relacionadas