【问题标题】:How to patch a PDF document如何修补 PDF 文档
【发布时间】:2016-08-30 07:14:30
【问题描述】:

作为我们自动化构建过程的一部分,我们希望在一系列 PDF 文件(我们的参考指南)中修补内部版本号。干净的方法是在 LibreOffice 中自动执行一些宏来更新字段并再次输出 PDF。

但是我想知道是否有更直接(但可以说是肮脏)的解决方案,包括在 PDF 文件中运行一些二进制查找和替换占位符。虽然内容似乎没有以明文形式出现在 PDF 中。有什么诀窍可以帮上忙吗?

【问题讨论】:

  • 应如何检索内部版本号?它应该在普通的 PDF 查看器中可见吗?还是应该藏在隐蔽的地方?
  • 它应该在文本中可见,例如在页脚或附录中
  • 在这种情况下,@Bruno 的回答很可能显示了快速而肮脏的解决方案是什么样的。

标签: pdf


【解决方案1】:

该数字不以明文形式提供,因为它是压缩内容流的一部分。

参加“Hello World!”例子。表示该文本的内容流可能如下所示:

2 0 obj
<</Length 65/Filter/FlateDecode>>stream
xœ+är
á26S°00SIá2PÐ5´ 1ôÝBÒ¸4<RsròÂó‹rR5C²€j@*\C¸¹ Çq°
endstream
endobj

当你解压二进制部分时,你会发现:

q
BT
36 806 Td
0 -18 Td
/F1 12 Tf
(Hello World!) Tj
0 0 Td
ET
Q

但是,以下语法也是正确的:

BT
/F1 12 Tf
88.66 806 Td
(ld!) Tj
-22 0 Td
(Wor) Tj
-15.33 0 Td
(llo) Tj
-15.33 0 Td
(He) Tj
ET

这种语法更难阅读,但如果你做所有的数学运算并根据文本矩阵的变化重新组织不同的文本 sn-ps,你会发现输出与语法的输出相同我们以前有过。

如果您的 PDF 是以直接的方式创建的,这意味着可以在解压缩的语法中轻松识别字符串,您可以获取页面的内容流,对其进行解压缩、更改、压缩和放置返回 PDF。

这也假设您要查找的字符串存在于页面的内容流中,而不是外部内容流中;即:在一个Form XObject中。

如果满足所有这些假设,您可以像这样使用 iText:

PdfReader reader = new PdfReader(src);
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
int total = reader.getNumberOfPages() + 1;
for (int i = 1; i < total; i++) {
    byte[] content = reader.getPageContent(i);
    byte[] alteredBytes = doSomethingWith(content);
    reader.setPageContent(i, alteredBytes);
}
stamper.close();
reader.close();

您必须实现doSomethingWith() 方法,以便它执行您需要的二进制搜索和替换。

重要提示:您要求一种快速而肮脏的方式,这是一种非常快速而肮脏的方式。如果我看到我的一名员工提交此代码,如果他或她不能给我任何体面的论据来使用此代码,我会当场解雇他或她。对于许多 PDF,此代码将失败,但它可能正是您在特定用例中所需要的。

您可能还想阅读:iText or iTextSharp rudimentary text edit

【讨论】:

  • 感谢您提供如此全面的答案。很有见地!我们将放弃这一刻,稍后再寻求干净的解决方案(自动化 libreoffice)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 2021-06-01
  • 2019-10-17
  • 1970-01-01
  • 2011-11-06
相关资源
最近更新 更多