Discord机器人Matplotlib生成Base64过长引发OSError问题求助
解决OSError: [Errno 36] File name too long问题
问题根源
你调用send_file(data[short_url], mimetype='image/png')时,data[short_url]是Base64编码的字符串,但Flask的send_file默认会把字符串参数当作文件路径处理,导致它尝试打开一个长度远超系统限制的文件名,触发错误。
修复方案
把Base64字符串解码为字节流,用io.BytesIO包装后传给send_file,让Flask识别为内存中的文件内容:
修改redirect_to_chart函数:
import base64 import io from flask import send_file @app.route("/api/url/<short_url>.png") def redirect_to_chart(short_url): with open("urls.json", "r") as f: data = json.load(f) if short_url in data: # 解码Base64为字节,包装成BytesIO对象 chart_bytes = io.BytesIO(base64.b64decode(data[short_url])) # 设置文件指针回到开头 chart_bytes.seek(0) # 传给send_file,可指定下载文件名 return send_file(chart_bytes, mimetype='image/png', download_name=f"{short_url}.png") return "Error"
额外优化建议
- 避免存储Base64字符串:Base64编码会让文件体积增加约33%,建议直接将Matplotlib生成的字节流保存为本地文件(比如
charts/{short_url}.png),然后在urls.json中存储文件路径而非Base64。这样既节省存储,也能让send_file直接读取本地文件,性能更好:# 在bcrt函数中替换Base64存储部分 import os # 确保charts目录存在 os.makedirs("charts", exist_ok=True) chart_path = f"charts/{short_url}.png" with open(chart_path, "wb") as f: f.write(chart_bytes.getvalue()) # 存储路径到json data[short_url] = chart_path # 在redirect_to_chart中直接传路径 return send_file(data[short_url], mimetype='image/png') - 清理过期文件:如果短链接有过期需求,定期清理
charts目录中的旧文件和urls.json中的过期条目,避免存储冗余。
内容的提问来源于stack exchange,提问作者yeet2675
相关产品推荐
相关产品推荐

