Python: Verifique se o arquivo enviado é jpg
-
06-07-2019 - |
Pergunta
Como posso verificar se um arquivo enviado por um usuário é um arquivo jpg real no Python (Google App Engine)?
Este é o quão longe eu tenho até agora:
Script recebe imagem via formulário HTML Post e é processado pelo código a seguir
...
incomming_image = self.request.get("img")
image = db.Blob(incomming_image)
...
Eu encontrei mimetypes.guess_type, mas ele não funciona para mim.
Solução
Se precisar de mais do que olhar para a extensão, de uma maneira seria ler o cabeçalho JPEG, e verificar se ele corresponde dados válidos. O formato para isso é:
Start Marker | JFIF Marker | Header Length | Identifier
0xff, 0xd8 | 0xff, 0xe0 | 2-bytes | "JFIF\0"
para um reconhecedor rápida seria:
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
No entanto isso não vai pegar todos os dados ruins no corpo. Se você quer uma verificação mais robusto, você pode tentar carregá-lo com PIL . por exemplo:
from PIL import Image
def is_jpg(filename):
try:
i=Image.open(filename)
return i.format =='JPEG'
except IOError:
return False
Outras dicas
Não há necessidade de utilizar e instalar o lybrary PIL para isso, existe o módulo padrão imghdr exatamente fited para este tipo de uso.
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 você tem uma imagem de um fluxo que você pode usar a opção de fluxo provavelmente, como este:
image_type = imghdr.what(filename, incomming_image)
Actualy isso funciona para mim em Pilões (mesmo se eu tiver tudo não terminou): no modelo 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()}
no controler de upload:
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
A solução mais geral é usar o Python obrigatório para o comando Unix "file". Para isso, instalar o pacote python-magia. Exemplo:
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()
Use PIL . Se ele pode abrir o arquivo, ele é uma imagem.
A partir do tutorial ...
>>> import Image
>>> im = Image.open("lena.ppm")
>>> print im.format, im.size, im.mode
O último byte de especificação de arquivo JPEG parece variar além de apenas e0. Capturando os três primeiros é 'suficientemente bom' de uma assinatura heurística para identificar com segurança se o arquivo é um jpeg. Por favor, veja abaixo proposta alterada:
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