Domanda

Come posso verificare se un file caricato da un utente è un vero file jpg in Python (Google App Engine)?

Questo è quanto sono arrivato adesso:

Lo script riceve l'immagine tramite HTML Form Post e viene elaborato dal seguente codice

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

Ho trovato mimetypes.guess_type, ma non funziona per me.

È stato utile?

Soluzione

Se hai bisogno di qualcosa di più che guardare l'estensione, un modo sarebbe leggere l'intestazione JPEG e verificare che corrisponda a dati validi. Il formato per questo è:

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

quindi un rapido riconoscimento sarebbe:

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

Tuttavia, questo non catturerà alcun dato negativo nel corpo. Se desideri un controllo più efficace, puoi provare a caricarlo con PIL . ad esempio:

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

Altri suggerimenti

Non è necessario utilizzare e installare il lybrary PIL per questo, c'è il modulo standard imghdr adatto esattamente per questo tipo di utilizzo.

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

import imghdr

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

Dato che hai un'immagine da uno stream, puoi usare l'opzione stream probabilmente in questo modo:

image_type = imghdr.what(filename, incomming_image)

In realtà questo funziona per me in Pylons (anche se non ho finito tutto): nel modello 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()}

nel controller di caricamento:

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 soluzione più generale consiste nell'utilizzare l'associazione Python al file "quot" di Unix; comando. Per questo, installa il pacchetto python-magic. Esempio:

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

Utilizza PIL . Se può aprire il file, è un'immagine.

Dal tutorial ...

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

L'ultimo byte della specifica del file JPEG sembra variare oltre a solo e0. Catturare i primi tre è "abbastanza buono" di una firma euristica per identificare in modo affidabile se il file è un jpeg. Consulta la proposta modificata di seguito:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top