生成图像 -> 以数据URI嵌入Flask中

10 投票
2 回答
9918 浏览
提问于 2025-04-18 16:04

我正在开发一个Flask应用,它可以生成动态图表,并通过jinja模板来展示这些图表。我想在模板中调用Flask应用里的一个函数,这个函数会返回png格式的数据,然后把这个数据嵌入到一个数据URI中。

这个链接的内容离我的目标很接近,不过我想避免使用url_for(也就是不想用路由)。相反,我希望直接使用数据URI来显示图像数据(比如img src="data:image/png;base64,...)。

2 个回答

7

这是一个基于你提供的例子的完整解决方案,经过测试可以正常工作:

from flask import Flask, render_template
import urllib
app = Flask(__name__)

@app.route("/simple.png")
def simple():
    import datetime
    import StringIO
    import random

    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
    from matplotlib.figure import Figure
    from matplotlib.dates import DateFormatter

    fig=Figure()
    ax=fig.add_subplot(111)
    x=[]
    y=[]
    now=datetime.datetime.now()
    delta=datetime.timedelta(days=1)
    for i in range(10):
        x.append(now)
        now+=delta
        y.append(random.randint(0, 1000))
    ax.plot_date(x, y, '-')
    ax.xaxis.set_major_formatter(DateFormatter('%Y-%m-%d'))
    fig.autofmt_xdate()
    canvas=FigureCanvas(fig)
    png_output = StringIO.StringIO()
    canvas.print_png(png_output)
    png_output = png_output.getvalue().encode("base64")

    return render_template("test.html", img_data=urllib.quote(png_output.rstrip('\n')))


if __name__ == "__main__":
    app.run()

模板:

<img src="data:image/png;base64,{{img_data}}"/>
16

与其把结果作为图片发送回来,不如把输出转换成base64格式:

try:  # Python 3
    from urllib.parse import quote
except ImportError:  # Python 2
    from urllib import quote
from base64 import b64encode
from io import BytesIO

png_output = BytesIO()
canvas.print_png(png_output)
data = b64encode(png_output.getvalue()).decode('ascii')
data_url = 'data:image/png;base64,{}'.format(quote(data))

这样做是让画布把内容写入一个内存中的文件,然后把生成的PNG数据编码成base64格式,并放在一个数据网址里。

撰写回答