烧瓶返回存储在数据库中的图像

我的图像存储在 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返回它。

有更好的解决办法吗?

121086 次浏览

Create a response object with the data and then set the content type header. Set the content disposition header to attachment if you want the browser to save the file instead of displaying it.

@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

Relevant: werkzeug.Headers and flask.Response

You can pass a file-like object and the header arguments to send_file to let it set up the complete response. Use io.BytesIO for binary data:

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

Prior to Flask 2.0, download_name was called attachment_filename.

Just wanted to confirm that dav1d's second suggestion is correct - I tested this (where obj.logo is a mongoengine ImageField), works fine for me:

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()),
download_name='logo.png',
mimetype='image/png'
)

Easier than manually creating a Response object and settings its headers.

Prior to Flask 2.0, download_name was called attachment_filename.

Suppose i have the stored image path with me. The below code helps to send image through.

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

uploads is my folder name where my image with 123.jpg is present.

[PS: The uploads folder should be in the current directory as of the your script file]

Hope it helps.

The following worked for me (for Python 3.7.3):

import io
import base64
# import flask
from PIL import Image


def get_encoded_img(image_path):
img = Image.open(image_path, mode='r')
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='PNG')
my_encoded_img = base64.encodebytes(img_byte_arr.getvalue()).decode('ascii')
return my_encoded_img


...
# your api code
...
img_path = 'assets/test.png'
img = get_encoded_img(img_path)
# prepare the response: data
response_data = {"key1": value1, "key2": value2, "image": img}
# return flask.jsonify(response_data )