Python内存中将BytesIO图片添加至PDF报错,求纯内存解决方案
解决fpdf加载内存中BytesIO图片的报错问题
这个问题我碰到过!原因很简单——你用的是旧版的fpdf(1.x系列),它的image()方法默认只认文件路径或者URL,你直接传buf.getvalue()返回的字节数据,它会把这个字节串当成路径去判断是不是URL,自然就触发startswith的类型错误了。
要完全在内存中解决这个问题,不用把图片存到本地,有两个靠谱的方案:
方案1:直接传入重置指针后的BytesIO对象
fpdf其实支持传入类文件对象,只是你需要先把BytesIO的指针移到流的开头(因为savefig之后指针会停在流的末尾,直接读的话会是空的),然后把整个BytesIO对象传给image()方法:
import matplotlib.pyplot as plt import io from fpdf import FPDF fig = plt.figure() # 这里写你的图表绘制代码,比如: # plt.plot([1,2,3], [4,5,6]) buf = io.BytesIO() fig.savefig(buf, format='png') buf.seek(0) # 关键步骤:将流的指针重置到起始位置 pdf = FPDF() pdf.add_page() pdf.image(buf, type='PNG') # 直接传入BytesIO对象,而非字节值 buf.close()
方案2:用Base64编码生成Data URI
如果方案1因为版本兼容问题不好用,还可以把图片字节流转换成Base64编码,生成data:格式的URI,这种方式也完全在内存中处理:
import matplotlib.pyplot as plt import io import base64 from fpdf import FPDF fig = plt.figure() # 省略图表绘制代码 buf = io.BytesIO() fig.savefig(buf, format='png') buf.seek(0) # 将字节流编码为Base64字符串 img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8') # 构建Data URI img_data_uri = f'data:image/png;base64,{img_base64}' pdf = FPDF() pdf.add_page() pdf.image(img_data_uri, type='PNG') buf.close()
两种方案都能实现完全在内存中把图表嵌入PDF,不用生成本地文件,之后你就可以把PDF保存到BytesIO里作为邮件附件发送啦。
内容的提问来源于stack exchange,提问作者Nathan
相关产品推荐
相关产品推荐

