查看: 122|回复: 3

Python使用Spire.PDF添加与提取PDF内嵌附件

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在项目交付中,PDF正文之外常带Excel工作簿、原始图片或补充说明。若把这些文件单独发送,接收者需要逐个下载、归档,容易漏掉材料。PDF附件可以把配套文件直接嵌入文档,让正文和资料一起交付。本文围绕脚本实现,使用Spire.PDF for Python完成两个操作:向PDF添加附件,以及从PDF中提取附件,并说明代码中的对象、参数和常见问题。

一、PDF附件与页面内容的区别
可以把带附件的PDF理解为“自带资料袋”的文档:页面展示正文,附件保存配套文件。附件与插入图片、添加超链接不同:插入图片会成为页面内容的一部分,打开页面即可看到;超链接通常只记录目标地址或路径,点击后访问目标位置;附件则是把文件本身嵌入PDF,需要通过支持附件的阅读器查看或另存。因此,把Excel作为附件加入PDF,不会把工作表转换成PDF页面,接收者提取后仍可用Excel打开和编辑原始工作簿。需要注意阅读器兼容性:查看附件时建议使用Adobe Acrobat等带附件面板的桌面阅读器,部分浏览器内置PDF查看器可能不显示附件入口。

二、环境准备
Spire.PDF for Python提供创建和处理PDF的接口,本文用它的附件接口直接操作PDF内部保存的文件,不需要手动打开阅读器添加或导出附件。安装依赖:
  1. pip install Spire.PDF
复制代码
在脚本中导入模块:
  1. from spire.pdf import *
  2. from spire.pdf.common import *
复制代码
运行示例前,将文件路径替换为本地实际路径。

三、向PDF添加附件
假设已有一份PDF报告Input.pdf,希望把原始数据Report.xlsx和配套图片Logo.png一起交付。操作分为四步:加载目标PDF;根据外部文件创建附件对象;把附件加入文档的附件集合;保存包含附件的新PDF。
  1. from spire.pdf import *
  2. from spire.pdf.common import *
  3. # 创建 PDF 文档对象
  4. doc = PdfDocument()
  5. # 加载目标 PDF
  6. doc.LoadFromFile("Input.pdf")
  7. # 根据外部文件创建附件对象
  8. attachment_one = PdfAttachment("Report.xlsx")
  9. attachment_two = PdfAttachment("Logo.png")
  10. # 将附件加入 PDF
  11. doc.Attachments.Add(attachment_one)
  12. doc.Attachments.Add(attachment_two)
  13. # 保存为新的 PDF 文件
  14. doc.SaveToFile("Attachments.pdf")
  15. # 释放资源
  16. doc.Close()
复制代码
代码说明:PdfAttachment("Report.xlsx")根据指定文件创建附件对象;doc.Attachments.Add()把附件对象加入当前PDF的附件集合。需要添加更多文件时,继续创建PdfAttachment对象并调用Add即可。附件不会占用页面空间,也不会改变正文排版。保存后打开Attachments.pdf,页面可能和原文档看起来相同,但在支持附件的阅读器中可以通过“附件”或“附加文件”面板找到嵌入文件。示例使用不同输入、输出文件名,因此原始Input.pdf保留,新增附件的结果保存到Attachments.pdf。还要考虑文件体积:附件保存的是文件数据本身,大型工作簿或高清图片会明显增加PDF大小,用于邮件发送或系统上传时要留意交付渠道的大小限制。

四、从PDF提取附件
收到带附件的PDF后,如果需要编辑其中的工作簿、整理配套图片,或把附件交给后续程序处理,可以把附件提取为独立文件。提取不需要解析PDF页面,也不涉及OCR;程序直接读取文档的附件集合,再把其中保存的文件数据写入磁盘。操作流程:加载带附件的PDF;获取文档的附件集合;遍历附件,读取文件名与数据;把每个附件保存到指定目录。运行前先创建Output\\ExtractedFiles文件夹。
  1. from spire.pdf import *
  2. from spire.pdf.common import *
  3. # Create a PdfDocument object
  4. doc = PdfDocument()
  5. # Load a PDF file
  6. doc.LoadFromFile("Attachments.pdf")
  7. # Get the attachment collection from the document
  8. collection = doc.Attachments
  9. # Loop through the collection
  10. if collection.Count > 0:
  11.     for i in range(collection.Count):
  12.         # Get a specific attachment
  13.         attachment = collection.get_Item(i)
  14.         # Get the file name and data of the attachment
  15.         fileName = attachment.FileName
  16.         data = attachment.Data
  17.         # Save it to a specified folder
  18.         data.Save("Output\\ExtractedFiles\" + fileName)
  19. doc.Close()
复制代码
代码说明:doc.Attachments返回文档的附件集合,collection.Count表示集合中的附件数量;没有附件时示例会跳过保存。遍历时get_Item(i)按索引获取附件,FileName提供文件名,Data.Save(path)把附件数据写入指定位置。对前一个示例,提取完成后输出目录中会出现Report.xlsx和Logo.png,这些文件可以分别交给对应软件打开,不必再通过PDF阅读器访问。路径中的反斜杠是Windows写法,在Python字符串中建议写成双反斜杠或使用原始字符串,避免转义问题。

五、提取时需要注意的细节
1. 输出目录:示例假定Output\\ExtractedFiles已经存在;实际项目中可以在提取前用Python的os.makedirs()自动创建目录。
2. 文件重名:不同PDF可能都包含名为Report.xlsx的附件,如果统一保存到同一文件夹,可能发生覆盖。批量提取时建议为每份PDF创建独立子文件夹;同一PDF内的同名附件,可以在文件名前添加索引。
3. 保存文件名:处理外部来源的PDF时,可用os.path.basename()取出附件名称中的文件名部分,再与目标目录组合,避免直接把附件名称中的路径信息用于保存。

六、常见问题
问:添加附件后,为什么PDF页面没有变化?
答:附件保存在文档内部,不属于页面上直接显示的内容。请使用支持附件功能的阅读器,在附件面板中查看。
问:添加附件后,还需要发送原始文件吗?
答:附件已随PDF保存时,接收者可以从PDF中提取出来。交付前最好打开输出文件检查一次,确认所需附件均已加入。
问:提取附件与提取PDF中的图片是一回事吗?
答:不是。提取附件是读取PDF内嵌的独立文件;提取页面图片是读取页面使用的图像资源。即使图片显示在PDF页面上,也不一定属于附件集合。
问:可以批量处理多个PDF吗?
答:可以。把单个PDF的处理逻辑放入文件遍历循环即可。批量提取时建议按PDF文件名分别建立输出目录,方便追溯来源并减少重名冲突。

七、小结
PDF附件适合把正文和配套资料组织在一起:正文保持便于阅读的版式,原始工作簿、图片和补充文件随文档一同保存。使用Spire.PDF for Python时,可以通过PdfAttachment和doc.Attachments.Add()添加附件,也可以遍历doc.Attachments,把已有附件保存为独立文件。脚本落地时重点关注阅读器兼容性、文件体积,以及提取时的输出目录和文件名处理。
回复

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python使用Spire.PDF添加与提取PDF内嵌附件

感谢分享,步骤写得很清楚,尤其是把附件和插入图片、超链接的区别讲明白了,这一点对刚接触PDF处理的人挺关键。之前我也遇到过把Excel塞进PDF后,用浏览器自带查看器怎么都找不到附件入口,换了Acrobat才看到面板,所以交付时确实得提醒对方用桌面阅读器打开。 另外大文件体积那段很有共鸣,有次往报告里塞了个几十兆的原始数据表,结果邮件直接发不出去,后来只能换成压缩包或者拆分交付。 提取部分想请教一下:帖子结尾好像停在 os.path.basena 这里了,后面是不是还有关于文件名处理的说明?我实际用的时候除了自动建目录,还会对 attachment.FileName 做一次 basename 并过滤掉路径分隔符和特殊字符,防止外部PDF里的附件名带 ../ 之类的东西把文件写到预期目录外面。不知道你那边有没有碰到类似情况,或者Spire.PDF对加密PDF里的附件提取有没有额外限制?
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python使用Spire.PDF添加与提取PDF内嵌附件

这篇内容结构很清晰,把“添加附件”和“提取附件”两条链路分开讲,并且点出了附件与页面内容、超链接的区别,实际项目里很容易混淆的地方也覆盖到了。代码示例比较直白,按加载文档、创建或遍历附件、保存、关闭资源的顺序组织,照着改路径基本能跑通。 补充几点实操建议:提取时不要直接用 fileName 拼路径,最好先做文件名清洗,去掉路径分隔符、冒号、问号等非法字符,避免外部 PDF 里的附件名带目录成分导致写到预期目录之外;输出目录可以用 os.makedirs(..., exist_ok=True) 自动创建,路径拼接用 os.path.join 会比手写反斜杠更稳。批量处理时,除了给每份 PDF 建子目录,还可以在文件名前加序号并检查目标文件是否已存在,防止同名附件覆盖。添加附件时如果配套文件很多,可以遍历目录批量创建 PdfAttachment,而不是逐个手写。最后,加载、添加、提取、保存这些步骤建议放在异常处理里,并确保关闭文档,避免批量运行时文件句柄未释放。整体上这篇适合作为落地参考,尤其提醒了文件体积和阅读器兼容性,这两点在交付场景里很实用。
回复 支持 反对

使用道具 举报

发表于 半小时前 | 显示全部楼层

Re: Python使用Spire.PDF添加与提取PDF内嵌附件

这个思路很实用,之前交付项目时也确实遇到过配套的Excel和图片散落各处、接收方漏归档的问题,把附件直接嵌进PDF里确实能让正文和资料一起走。代码示例写得也比较清楚,从加载、创建PdfAttachment、Add到Save,再到提取时遍历count和get_Item,流程完整。提两个自己踩过的小坑供参考:一是跨平台时保存路径别硬编码反斜杠,用os.path.join拼出来更稳妥,提取前顺便os.makedirs(outdir, exist_ok=True)一次搞定,避免目录不存在报错;二是附件体积尽量在交付前看看,几张大图或者大工作簿嵌进去后PDF可能膨胀得很明显,发给邮件系统前最好压一压或者做下分批处理。另外如果PDF本身设了权限或者加密,某些情况下附件读写可能受限,遇到读不出来可以先确认文档是否受保护。整体来说这篇对脚本操作附件的说明已经很到位,感谢分享。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-5 03:05 , Processed in 0.022282 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部