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


76

我的图像存储在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

有更好的解决方案吗?


Answers:


131

用数据创建一个响应对象,然后设置内容类型标题。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.Headersflask.Response

您可以将类似文件的Oject和header参数传递send_file给它,以设置完整的响应。使用io.BytesIO二进制数据:

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

3
send_file发送后是否关闭文件对象?如果不是BytesIO,而是其他一些需要调用close()的文件对象,谁会调用它?
巴鲁克

2
使用Python 3和Flask 0.12,提供二进制字符串(b'<binary image data>')可能会导致UnicodeErrorsend_file()可能会更好。
GergelyPolonkai

1
@Baruch使用with子句?
MrR

43

只是想确认dav1d的第二个建议是正确的-我对此进行了测试(其中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对象和设置其标题容易。


10

假设我已经存储了图像路径。以下代码有助于通过发送图像。

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:上载文件夹应位于脚本文件的当前目录中]

希望能帮助到你。


4
如果图像在内存中该怎么办。
MrR

2

以下对我有用(适用于Python 3.7.3):

import io
import base64
import flask

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 )

在服务器端使用此代码,如何在javascript中对其进行解码?将字符串编码为ascii,然后将字节解码为base 64并将其另存为图像?
QH

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.