Python: compruebe si el archivo cargado es jpg
-
06-07-2019 - |
Pregunta
¿Cómo puedo verificar si un archivo cargado por un usuario es un archivo jpg real en Python (Google App Engine)?
Esto es lo lejos que llegué ahora:
El script recibe la imagen a través de la publicación de formulario HTML y se procesa con el siguiente código
...
incomming_image = self.request.get("img")
image = db.Blob(incomming_image)
...
Encontré mimetypes.guess_type, pero no me funciona.
Solución
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 para esto es:
Start Marker | JFIF Marker | Header Length | Identifier
0xff, 0xd8 | 0xff, 0xe0 | 2-bytes | "JFIF\0"
entonces un reconocimiento rápido sería:
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 capturará ningún dato incorrecto en el cuerpo. Si desea una verificación más sólida, puede intentar cargarla 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
Otros consejos
No es necesario usar e instalar la biblioteca PIL para esto, existe el módulo estándar imghdr que se ajusta exactamente a 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 tiene una imagen de una transmisión, puede usar la opción de transmisión probablemente así:
image_type = imghdr.what(filename, incomming_image)
En realidad, esto funciona para mí en Pylons (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 el controlador 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
Una solución más general es utilizar el enlace de Python al archivo Unix " mando. Para esto, instale 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()
Utilice PIL . Si puede abrir el archivo, es una imagen.
Del tutorial ...
>>> import Image
>>> im = Image.open("lena.ppm")
>>> print im.format, im.size, im.mode
El último byte de la especificación del archivo JPEG parece variar más allá de solo e0. Capturar los primeros tres es "suficientemente bueno" de una firma heurística para identificar de manera confiable si el archivo es un jpeg. Consulte la propuesta modificada a continuación:
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