web-dev-qa-db-ja.com

Flaskデータベースに保存された画像を返す

私の画像はMongoDBに保存されているので、クライアントに返したいのですが、コードは次のようになります。

@app.route("/images/<int:pid>.jpg")
def getImage(pid):
    # get image binary from MongoDB, which is bson.Binary type
    return image_binary

しかし、Flaskでバイナリを直接返すことはできないようです?これまでの私の考え:

  1. 画像バイナリのbase64を返します。問題は、IE <8はこれをサポートしていないことです。
  2. 一時ファイルを作成し、send_fileで返します。

より良い解決策はありますか?

58
wong2

データを含む応答オブジェクトを作成し、コンテンツタイプヘッダーを設定します。ブラウザでファイルを表示する代わりに保存する場合は、コンテンツ処理ヘッダーをattachmentに設定します。

@app.route('/images/<int:pid>.jpg')
def get_image(pid):
    image_binary = read_image(pid)
    response = make_response(image_binary)
    response.headers.set('Content-Type', 'image/jpeg')
    response.headers.set(
        'Content-Disposition', 'attachment', filename='%s.jpg' % pid)
    return response

関連: werkzeug.Headers および flask.Response

ファイルのようなオブジェクトをsend_fileに渡し、ヘッダー引数を渡して完全な応答を設定できます。バイナリデータにio.BytesIOを使用します。

return send_file(
    io.BytesIO(image_binary),
    mimetype='image/jpeg',
    as_attachment=True,
    attachment_filename='%s.jpg' % pid)
97
dav1d

Dav1dの2番目の提案が正しいことを確認したかっただけです-obj.logoがmongoengine ImageFieldである場合、これをテストしました。

import io

from flask import current_app as app
from flask import send_file

from myproject import Obj

@app.route('/logo.png')
def logo():
    """Serves the logo image."""

    obj = Obj.objects.get(title='Logo')

    return send_file(io.BytesIO(obj.logo.read()),
                     attachment_filename='logo.png',
                     mimetype='image/png')

Responseオブジェクトを手動で作成し、ヘッダーを設定するよりも簡単です。

39
Jaza

私は私と一緒に保存された画像パスを持っていると仮定します。以下のコードは、画像を送信するのに役立ちます。

from flask import send_file
@app.route('/get_image')
def get_image():
    filename = 'uploads\\123.jpg'
    return send_file(filename, mimetype='image/jpg')

uploadsは、123.jpgの画像が存在するフォルダー名です。

[PS:アップロードフォルダーは、スクリプトファイルの現在のディレクトリにある必要があります]

それが役に立てば幸い。

5