Sto usando il pallone per la mia applicazione. Mi piacerebbe inviare un'immagine (generata dinamicamente da PIL) al client senza salvare su disco.Come inviare un'immagine generata da PIL al browser?
Qualche idea su come procedere?
Sto usando il pallone per la mia applicazione. Mi piacerebbe inviare un'immagine (generata dinamicamente da PIL) al client senza salvare su disco.Come inviare un'immagine generata da PIL al browser?
Qualche idea su come procedere?
In primo luogo, è possibile salvare l'immagine in un tempfile e rimuovere il file locale (se ne avete uno):
from tempfile import NamedTemporaryFile
from shutil import copyfileobj
from os import remove
tempFileObj = NamedTemporaryFile(mode='w+b',suffix='jpg')
pilImage = open('/tmp/myfile.jpg','rb')
copyfileobj(pilImage,tempFileObj)
pilImage.close()
remove('/tmp/myfile.jpg')
tempFileObj.seek(0,0)
In secondo luogo, impostare il file temporaneo alla risposta (come da this stackoverflow question):
from flask import send_file
@app.route('/path')
def view_method():
response = send_file(tempFileObj, as_attachment=True, attachment_filename='myfile.jpg')
return response
Non funziona più: 'TypeError: 'file' oggetto non è richiamabile' – letmaik
@neo - Grazie, aggiornato per send_file –
Qual è il file creato dinamicamente qui? – user1953366
Ho anche faticato nella stessa situazione. Infine, ho trovato la sua soluzione usando un'applicazione WSGI, che è un oggetto accettabile per "make_response" come argomento.
from Flask import make_response
@app.route('/some/url/to/photo')
def local_photo():
print('executing local_photo...')
with open('test.jpg', 'rb') as image_file:
def wsgi_app(environ, start_response):
start_response('200 OK', [('Content-type', 'image/jpeg')])
return image_file.read()
return make_response(wsgi_app)
Si prega di sostituire "l'apertura di immagine" operazioni con opportune operazioni di Pil.
Questo funziona magnificamente :) – cybertoast
Si scopre che boccetta fornisce una soluzione (RTM a me!):
from flask import abort, send_file
try:
return send_file(image_file)
except:
abort(404)
Ecco una versione senza alcun file temporanei e simili (vedi here):
def serve_pil_image(pil_img):
img_io = StringIO()
pil_img.save(img_io, 'JPEG', quality=70)
img_io.seek(0)
return send_file(img_io, mimetype='image/jpeg')
Per utilizzare nel codice semplicemente
@app.route('some/route/')
def serve_img():
img = Image.new('RGB', ...)
return serve_pil_image(img)
Questa è una risposta di gran lunga superiore alla risposta accettata. – jrs
Significa che devi essere in grado di mantenere l'intera immagine in memoria in una sola volta, giusto? Potrebbe essere un problema con immagini enormi o altri tipi di download. – Eli
@Eli per quei casi sembra più ragionevole usare un file temporaneo. Ad ogni modo, enormi file generati dinamicamente non sono comuni. – erickrf
Flask non sembra avere un solido supporto per lo streaming di dati binari che è possibile Generare con un generatore Python. Probabilmente dovrai memorizzare l'immagine in memoria e inviarla. – millimoose