如何从 svg 字节流渲染 svg 图像

How to render an svg image from an svg byte stream

这个 python / flask 脚本创建了一个 svg QR 代码字节流,但是当我尝试使用 Jinja2 模板 {{ qr[0] }} 呈现它时,它呈现为文本。如何将其渲染为图像?正如您从下面的代码中看到的,我已经成功地将数据传输到客户端——我不需要帮助——唯一的问题是数据格式错误——一个 svg 字节流——而我想显示该数据作为图像。

为了澄清起见,我必须导出 render_template 中的二维码,因为我还有其他变量对二维码有贡献,也需要导出。因此,<img src="{{ url_for('qr') }}">方法不起作用。

同样,我不希望数据在 URL 中可见。

import pyqrcode
from io import BytesIO

@app.route('/qr/<id>/<price>', methods=['GET', 'POST'])
def qr(id,price):
    if id:
        data = id+price
        basestring = pyqrcode.create(data, error='H')
        stream = BytesIO()
        basestring.svg(stream, scale=5, module_color='#802929', background='#FFFFFF')
        qr = stream.getvalue(), 200, {
            'Content-Type': 'image/svg+xml',
            'Cache-Control': 'no-cache, no-store, must-revalidate',
            'Pragma': 'no-cache',
            'Expires': '0'}

    return render_template('qr.html', qr=qr, data=data)

这是 HTML 页面上当前呈现为文本的一部分:

b'\n<path transform="scale(5)" stroke="#802929" class="pyqrline" d="M4 4.5h7m1 0h1m1 0h2m2 0h2m1 0h3m1 0h1m1 0h2m1 0h2m2 0h5m2 0h4m1 0h1m1 0h4m2 0h7m-57 1h1m5 0h1m2 0h1m1 0h1m2 0h5m1 0h2m3 0h1m4 0h1m1 0h1m1 0h5m4 0h1m3 0h1m2 0h1m5 0h1m-57 1h1m1 0h3m1 0h1m1 0h1m1 0h4m3 0h1m3 0h1m2 0h2m3 0h2m3 0h1m2 0h1m1 0h4m1 0h4m2 0h1m1 0h3m1 0h1m-57 1h1m1 0h3m1 0h1m3 0h3m2 0h1m2 0h3m1 0h1m8 0h2m1 0h2m3 0h2m1 0h3m2 0h1m2 0h1m1 0h3m1 0h1m-57 1h1m1 0h3m1 0h1m1 0h1m1 0h1m1 0h1m2 0h1m5 0h1m3 0h6m1 0h1m1 0h3m3 0h3m1 0h1m2 0h1m2 0h1m1 0h3m1 0h1m-57 1h1m5 0h1m2 0h1m5 0h1m2 0h1m6 0h2m3 0h1m1 0h2m1 0h7m1 0h4m3 0h1m5 0h1m-57 1h7m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h1m1 0h7m-49 1h1m3 0h3m1 0h5m1 0h1m3 0h1m3 0h1m1 0h1m2 0h1m3 0h3m1 0h1m1 0h2m1 0h1m-44 1h2m4 0h1m2 0h2m1 0h4m4 0h6m2 0h5m1 0h1m5 0h3m2 0h1m1 0h1m1 0h1m1 0h1m-57

在模板中使用之前,您必须对字节流进行解码。此外,您还必须使用 Jinja 的 |安全过滤器。

import pyqrcode
from io import BytesIO

@app.route('/qr/<id>/<price>', methods=['GET', 'POST'])
def qr(id, price):
    data = id + price
    qrcode = pyqrcode.create(data, error='H')
    stream = BytesIO()
    # Added: Disable XML declaration and SVG namespace
    # Removed: background='#FFFFFF' since it is the default
    qrcode.svg(stream, scale=5, xmldecl=False, svgns=False, module_color='#802929')
    qr = stream.getvalue().decode('utf-8')
    return render_template('qr.html', qr=qr, data=data)

在您的模板中:

<div>{{ qr | safe }}</div>

或者使用另一个 QR code lib

甚至更短
import segno

@app.route('/qr/<id>/<price>', methods=['GET', 'POST'])
def qr(id, price):
    data = id + price
    qr = segno.make(data, error='H')
    return render_template('qr.html', qr=qr, data=data)

Jinja 模板:

<div>{{ qr.svg_inline(dark='#802929', scale=5) | safe }}</div>