Flask中Matplotlib生成图片页面显示异常问题求助
问题:Matplotlib生成的PNG图片在Web页面显示异常,新窗口打开正常
我正在开发Web应用,需展示API生成的图片:API将Matplotlib图表转为PNG后通过io库发送给主应用。页面上的图片几乎总是显示异常,但右键在新窗口打开则显示正常。
异常图片:
发送图表的API代码:
@app.route('/send-data-a', methods=['GET']) def send_data_user_dynamic(): # ...生成图表的代码... image_stream1 = io.BytesIO() plt.savefig(image_stream1, format='png') image_stream1.seek(0) plt.close(fig) return send_file(image_stream1, mimetype='image/png')
主应用代码(曾尝试添加时间戳使链接唯一,无效):
@app.route('/data', methods=['GET']) def data(): timestamp = int(time.time()) user_dynamic = requests.get(f'http://127.0.0.1:5000/send-data-a?timestamp={timestamp}') user_amount = requests.get(f'http://127.0.0.1:5000/send-data-b?timestamp={timestamp}') kp_month = requests.get(f'http://127.0.0.1:5000/send-data-c?timestamp={timestamp}') kp_week = requests.get(f'http://127.0.0.1:5000/send-data-d?timestamp={timestamp}') return render_template('second.html', user_dynamic=user_dynamic.url, user_amount=user_amount.url, kp_month=kp_month.url, kp_week=kp_week.url) if __name__ == '__main__': app.run(debug=True, port=5001)
HTML模板代码:
<div class="diagram"> <img src="{{ user_dynamic }}" alt="user_dynamic"> <figcaption>some text</figcaption> </div>
解决方案
核心问题:重复请求导致流读取异常
你当前主应用用requests.get提前请求了图片API,但只把URL传给模板,这会让API被请求两次:一次是主应用的请求,一次是浏览器加载<img>的请求。BytesIO流在第一次读取后位置会偏移,第二次请求返回的就是损坏的数据。修复步骤:
修改主应用代码,直接构造URL传递给模板
去掉提前发起的requests.get,直接生成URL:@app.route('/data', methods=['GET']) def data(): timestamp = int(time.time()) # 直接构造URL,不提前请求API user_dynamic = f'http://127.0.0.1:5000/send-data-a?timestamp={timestamp}' user_amount = f'http://127.0.0.1:5000/send-data-b?timestamp={timestamp}' kp_month = f'http://127.0.0.1:5000/send-data-c?timestamp={timestamp}' kp_week = f'http://127.0.0.1:5000/send-data-d?timestamp={timestamp}' return render_template('second.html', user_dynamic=user_dynamic, user_amount=user_amount, kp_month=kp_month, kp_week=kp_week)优化API的send_file参数
添加缓存控制和文件名参数,确保浏览器正确识别资源:return send_file( image_stream1, mimetype='image/png', attachment_filename='user_dynamic.png', cache_timeout=0 # 禁用缓存 )彻底清理Matplotlib资源
避免残留图表影响后续生成:plt.savefig(image_stream1, format='png') image_stream1.seek(0) plt.close(fig) plt.clf() # 清空当前图表 plt.close('all') # 关闭所有图表窗口添加禁止缓存的响应头(可选)
进一步防止浏览器缓存旧图片:from flask import make_response # ...生成流的代码... response = make_response(send_file(image_stream1, mimetype='image/png', cache_timeout=0)) response.headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0' response.headers['Pragma'] = 'no-cache' return response
内容的提问来源于stack exchange,提问作者Sarttex
相关产品推荐
相关产品推荐

