flask如何返回图片流?

我的flask需要通过传入的url参数,通过qrcode库生成二维码图片,然后将它写入流中返回。

import qrcode
qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=10,
    border=1
)
qr.add_data(url)
img = qr.make_image()

生成的qrcode.image.pil.PilImage对象并没有太多的方法可用,

但可以通过:img.convert("RGBA”)能得到一个PIL.Image.Image对象
我想请教:
1.如何把这个Image对象,通过流读出来。
2.如何把这个流通过flask写给请求者。

阅读 20.6k
3 个回答

PilImage 的源码看到有个save 方法

def save(self, stream, kind=None):
        if kind is None:
            kind = self.kind
        self._img.save(stream, kind)

那么针对这个stream可以用Python的io库搞定。

参考 Flask-QRcode中的实现即可

def qrcode(data, version=None, error_correction='L', box_size=10, border=0, fit=True):
    """ makes qr image using qrcode as qrc See documentation for qrcode package for info"""
    qr = qrc.QRCode(
        version=version,
        error_correction=correction_levels[error_correction],
        box_size=box_size,
        border=border
    )
    qr.add_data(data)
    qr.make(fit=fit)

    # creates qrcode base64
    out = BytesIO()
    qr_img = qr.make_image()
    qr_img.save(out, 'PNG')

    return u"data:image/png;base64," + base64.b64encode(out.getvalue()).decode('ascii')

具体未测,你可以试试。

import sys
from flask.ext.redis import Redis
import qrcode
from io import BytesIO
from flask import send_file

app = Flask(__name__)


@app.route("/image")
def test_qrcode():

    qr = qrcode.QRCode(
    version=4,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=10,
    border=1
    )
    qr.add_data("http://segmentfault.com/q/1010000004052685")
    img = qr.make_image()

    byte_io = BytesIO()
    img.save(byte_io, 'PNG')
    byte_io.seek(0)

    return send_file(byte_io, mimetype='image/png')


if __name__ == "__main__":

    app.run(host="localhost", port=5000, debug=True)

刚好我写过个功能,代码贴一下吧。cache_timeout=0非常重要,不然有可能被取得上次缓存。
文件地址:https://github.com/ZhangBohan/KoalaAPI/blob/master/KoalaAPI/api_v1/qr_views.py

import qrcode
from StringIO import StringIO
from flask import send_file, request

from . import api_v1


@api_v1.route('/qrcode', methods=['GET', 'POST'])
def v1_qrcode():
    box_size_arg = 'box_size'
    border_arg = 'border'
    box_size = request.args.get(box_size_arg, 10)
    border = request.args.get(border_arg, 1)
    url = request.args.get('url')

    qr = qrcode.QRCode(
        version=1,
        error_correction=qrcode.constants.ERROR_CORRECT_L,
        box_size=box_size,
        border=border,
    )
    if request.method == 'GET':
        data = {}
        if url:
            data = url
        else:
            for key, value in request.args.items():
                if key != border_arg and key != border_arg and key != url:
                    data[key] = value[0]
        qr.add_data(data)
    else:
        qr.add_data(request.data)
    qr.make(fit=True)

    img = qr.make_image()
    return _serve_pil_image(img)


def _serve_pil_image(pil_img):
    img_io = StringIO()
    pil_img.save(img_io, 'PNG')
    img_io.seek(0)
    return send_file(img_io, mimetype='image/png', cache_timeout=0)

代码基于python2的,如果是python3考虑把StringIO改为io.BytesIO

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
1 篇内容引用
推荐问题