如何通过Pikepdf与Python实现无冗余磁盘读写的PDF合并
解决方案:无多余磁盘IO的PDF合并与邮件发送
核心思路
利用pikepdf支持从字节流读取PDF、以及将Pdf对象直接导出为字节的特性,全程仅保留读取磁盘static.pdf的操作,其余步骤均在内存完成:
- 从磁盘加载
static.pdf为pikepdf.Pdf对象 - 用img2pdf生成内存中的dynamic PDF字节数据
- 直接从字节流加载dynamic PDF为pikepdf.Pdf对象
- 合并两个PDF的页面
- 将合并后的PDF导出为字节,直接作为邮件附件发送
代码实现
import io import pikepdf import img2pdf import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders # 1. 从磁盘读取static.pdf到内存Pdf对象 static_pdf = pikepdf.open("static.pdf") # 2. 用img2pdf动态生成内存中的dynamic.pdf字节流 # 替换为你的实际图片/参数生成逻辑 image_sources = ["user_upload_1.jpg", "user_upload_2.png"] dynamic_pdf_bytes = img2pdf.convert(image_sources) # 3. 从字节流加载dynamic.pdf为Pdf对象 dynamic_pdf = pikepdf.open(io.BytesIO(dynamic_pdf_bytes)) # 4. 合并页面:将dynamic的页面追加到static后方 static_pdf.pages.extend(dynamic_pdf.pages) # 5. 将合并后的PDF导出为内存字节流 final_pdf_buffer = io.BytesIO() static_pdf.save(final_pdf_buffer) final_pdf_buffer.seek(0) # 重置指针到起始位置 # 6. 作为邮件附件发送(替换为你的SMTP配置) msg = MIMEMultipart() msg['Subject'] = "合并完成的PDF文件" msg['From'] = "sender@example.com" msg['To'] = "recipient@example.com" # 添加附件 part = MIMEBase('application', 'octet-stream') part.set_payload(final_pdf_buffer.read()) encoders.encode_base64(part) part.add_header('Content-Disposition', 'attachment', filename="final.pdf") msg.attach(part) # 发送邮件 with smtplib.SMTP('smtp.example.com', 587) as server: server.starttls() server.login("your_username", "your_password") server.send_message(msg)
关键细节说明
- pikepdf的
open()方法支持直接接收io.BytesIO对象,无需将dynamic PDF写入磁盘即可加载 Pdf.save()方法可写入io.BytesIO,直接得到合并后的PDF字节,完全跳过磁盘存储步骤- 导出的字节与磁盘写入再读取的结果完全一致,pikepdf基于QPDF实现,保证PDF格式的标准性与正确性
内容的提问来源于stack exchange,提问作者Della
相关产品推荐
相关产品推荐

