web-dev-qa-db-ja.com

PILによって生成された画像をブラウザに送信する方法は?

アプリケーションにflaskを使用しています。ディスクに保存せずに(PILによって動的に生成された)画像をクライアントに送信したいです。

これを行う方法はありますか?

47
user795243

まず、イメージを tempfile に保存し、ローカルファイル(ある場合)を削除します。

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)

次に、一時ファイルを応答に設定します( 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
20
Adam Morris

これは、一時ファイルなどのないバージョンです( 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')

コードで使用するには、単に

@app.route('some/route/')
def serve_img():
    img = Image.new('RGB', ...)
    return serve_pil_image(img)
150
Mr. Mr.

Mr. Mr.は実に素晴らしい仕事をしました。 StringIO()の代わりにBytesIO()を使用する必要がありました。

def serve_pil_image(pil_img):
    img_io = BytesIO()
    pil_img.save(img_io, 'JPEG', quality=70)
    img_io.seek(0)
    return send_file(img_io, mimetype='image/jpeg')
7
Dan Erez

私も同じ状況で苦労していました。最後に、引数として「make_response」の受け入れ可能なオブジェクトであるWSGIアプリケーションを使用したソリューションを見つけました。

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)

「オープニングイメージ」操作を適切なPIL操作に置き換えてください。

7
cocoatomo

flaskが解決策を提供していることがわかりました(自分にとってはrtmです!):

from flask import abort, send_file
try:
    return send_file(image_file)
except:
    abort(404)
7
cybertoast