You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:54:07