添加PDF文档链接

时间:2014-05-23 16:45:31

标签: python pdf pdf-generation pypdf

我需要以编程方式分析和组合几个(数百个)PDF文档,并以专门的方式将页面链接在一起。每个PDF都包含链接所属的每个位置的文本,指示它应链接到的位置。我正在使用pdfminer来提取链接所在的位置和文本;现在我只需要实际创建这些链接。

我做了一些研究并得出结论认为PyPDF2可以做到这一点。无论如何,有一种看似简单的addLink方法声称可以完成工作。我无法让它发挥作用。

from PyPDF2 import PdfFileWriter
from PyPDF2.pdf import RectangleObject

out = PdfFileWriter()

out.insertBlankPage(800, 1000)
out.insertBlankPage(800, 1000)

# rect = [400, 400, 600, 600] # This doesn't seem to work either
rect = RectangleObject([400, 400, 600, 600])
out.addLink(0, 1, rect) # link from first to second page

with open(r'C:\temp\test.pdf', 'wb') as outf:
    out.write(outf)

上面的代码生成了一个漂亮的两页PDF,其中没有任何内容,至少据我所知。有没有人知道如何实现这一目标?或者至少表明我哪里出错了?

解决方案不必使用PyPDF2,只要该库是免费许可的。严格来说,Python甚至不是一个要求,但如果不将其他语言侵入到我当前的结构中,那将很好。

1 个答案:

答案 0 :(得分:5)

这似乎是addLink实现中的错误,或者该方法可能仅适用于较旧或不同的链接语法。无论如何,从问题中的示例代码检查输出PDF的结构揭示了这个小宝石:

6 0 obj
<<
/Dest [ 4 0 R /FitV 826 ]
/Type /Annot
/Rect RectangleObject([400, 400, 600, 600])
/Border [ 0 0 0 ]
/P IndirectObject(5, 0)
/Subtype /Link
>>

这有几个问题。最明显的是RectangleObjectIndirectObject是Python库的构造,不是有效的PDF结构。 /Dest似乎也有一个我没有要求的神秘魔法参数。此外,/P将是多余的(对包含此链接的页面的引用),即使它是以不将Python对象强制转换为PDF结构的方式实现的。简而言之,毫无疑问,这种联系已经破裂。

使用源消息来消除崩溃错误,结果是需要进行两次更改*才能使链接进入正常工作状态:从/Rect更改NameObject的内部表示转到ArrayObject,并将/P引用更改为指向页码,而不是实际对象。这些更改使示例代码生成有效输出:

6 0 obj
<<
/Dest [ 4 0 R /FitV ]
/Type /Annot
/Rect [ 400 400 600 600 ]
/Border [ 0 0 0 ]
/P 0
/Subtype /Link
>>

Etvoilà,链接在输出中完全按预期工作!我还从826值中移除了魔术/Rect,因为它可能不是合法参数,具体取决于缩放级别,并且它实际上不应该是硬编码的。


*在得出结论此修复程序按预期工作后,我确实认为将/Rect保留为NameObject并向其传递一个类似于输出的字符串(例如'[ 400 400 600 600 ]')也会奏效。这可能是为了获得最大的灵活性,但肯定是出乎意料的。


更新:我整理并提交了一个更完整的修补程序(后代link to the patch),因此上述问题都应该修复,从版本1.22