Question

Comment puis-je vérifier si un fichier téléchargé par un utilisateur est un véritable fichier jpg en Python (Google App Engine)?

Voici à quel point je suis arrivé maintenant:

Le script reçoit l'image via HTML Form Post et est traité par le code suivant

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

J'ai trouvé mimetypes.guess_type, mais cela ne fonctionne pas pour moi.

Était-ce utile?

La solution

Si vous avez besoin de plus que de regarder l'extension, une solution serait de lire l'en-tête JPEG et de vérifier qu'il correspond aux données valides. Le format pour ceci est:

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

donc un identifiant rapide serait:

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

Cependant, cela n'attrapera aucune mauvaise donnée dans le corps. Si vous souhaitez une vérification plus robuste, vous pouvez essayer de la charger avec PIL . par exemple:

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

Autres conseils

Inutile d'utiliser et d'installer le répertoire PIL pour cela, il existe le module standard imghdr parfaitement adapté à ce type d'utilisation.

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

import imghdr

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

Comme vous avez une image d'un flux, vous pouvez utiliser l'option stream probablement comme ceci:

image_type = imghdr.what(filename, incomming_image)

En fait, cela fonctionne pour moi dans les pylônes (même si je n’ai pas tout fini): dans le modèle 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()}

dans le contrôleur de téléchargement:

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

Une solution plus générale consiste à utiliser la liaison Python au fichier "Unix" Unix. commander. Pour cela, installez le paquet python-magic. Exemple:

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

Utilisez la PIL . S'il peut ouvrir le fichier, c'est une image.

À partir du tutoriel ...

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

Le dernier octet de la spécification de fichier JPEG semble varier au-delà de e0. Capturer les trois premiers est «assez bon» d'une signature heuristique pour identifier de manière fiable si le fichier est un fichier jpeg. Veuillez voir ci-dessous la proposition modifiée:

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top