【问题标题】:How to get the names of AcroField revisions in iText?如何在 iText 中获取 AcroField 修订的名称?
【发布时间】:2013-06-14 16:38:50
【问题描述】:

我目前正在开发一种用于在 pdf 文档上应用和验证数字签名的工具。我了解 pdf 文档中的每个签名都适用于 AcroFields 的某个版本。每次用户更改某些输入(即通过填写 pdf 表单)时,都会创建一个新的修订版本。

我的问题是:如何从 AcroFields 对象中检索 所有修订?如果我有这样的名称,我知道如何获得 single 修订:

AcroFields fields = ...;
fields.getRevision("revision1");

但我怎样才能检索所有修订(或至少他们的名字)?到目前为止,我还没有在 iText API 和网络中找到任何东西。

我在 2.1.7 版本中使用 iText。

感谢和问候, 汤姆

【问题讨论】:

  • 未命名修订。 (Itext 只是将已签名的修订与底层签名的名称相关联,而 itext 本质上不关心其他修订。) Itext 不比较修订。

标签: pdf itext signature acrofields


【解决方案1】:

先放一些背景

PDF 文件通常由标题、正文、交叉引用信息和预告片组成,见下图 2。更新此类 PDF 文件时,您可以选择

  • 重新构建整个文档并整合所有更改(这会导致 PDF 再次像原始文件一样形成)
  • 或者您可以将正文元素的更改和交叉引用附加到文档中,并添加一个新的预告片也引用以前的预告片(这会导致形成如下图 3 所示的 PDF)。

不过,实际上有一些介于两者之间的形式。例如。一些工具只是切断了原始文档的交叉引用和预告片,然后添加它们新的或更改的正文元素、新的完整交叉引用和新的预告片,而没有任何对以前状态的任何反向引用。

(图片复制自 PDF 规范 ISO 32000-1:2008

对于如图 3 所示形成的 PDF,我们手头有 PDF 的不同状态的历史记录,每个状态都从文件开头开始,一直延伸到并包括其中一个预告片。这些状态通常被称为文档的修订版,并且文档的每个修订版显然都反映了 PDF 表单信息的某些状态,我假设这就是您所说的AcroFields 的修订版

与您的假设相反,这些修订版本身没有名称。除非您使用 ID 的第二部分(对于不同的修订版应该不同),否则 AFAIK 不用作 iText 中任何内容的名称。

预告片停止和下一次正文更新开始的确切点有些不精确。一方面,规范中有一些迫在眉睫的选择(不同的可能换行符、忽略的空格、忽略的注释行),另一方面,许多 PDF 制作者无论如何都超出了规范。这与上面提到的完整更新和增量更新之间的中间变化相结合,有时会使提取修订的过程有些麻烦。

有一种特殊的修订情况,可以高度可靠地识别:签名修订,即最后一次正文更新包含文档集成签名的修订。由于文档的签名字节范围必须包含所有文档修订版本,但为签名本身留下的空白(至少要被 Adob​​e 软件接受并符合 PAdES 和 PDF-2 标准),文件的确切结尾这种情况下的修订可以从签名信息中推断出来:

更多详情here

您的问题的一些答案

我了解 pdf 文档中的每个签名都应用于 AcroFields 的某个修订版。

如上所述,每个都应用于文档的某个修订,这意味着表单数据的某个状态或“修订”。

每次用户更改某些输入(即通过填写 pdf 表单)时,都会创建一个新版本。

不一定。如上所述,更新的中间方法有很多。

仅当更改已签署最新修订版的文档的信息时,如果该签名不被删除或无效,则需要进行适当的增量更新。否则,更新者可以获取最后一个签名之后添加的所有信息,使用他希望的任何内容创建自己的更新,并将该更新附加到文档的最后一个签名修订版。此更新甚至可能包含多个虚拟更新块,目的是让您相信某些中间版本确实存在。

因此,只有签名的修订才能以某种方式被认为是真实的。 iText 仅提供对此类签名修订的访问。

我的问题是:如何从 AcroFields 对象中检索所有修订?

您可以使用

提取所有已签名的文档修订
InputStream revisionStream = fields.extractRevision("name");

并在单独的PdfReader 实例中打开它们。然后,您可以通过查询为该修订打开的相应 PdfReaderAcroFields 实例来访问每个已签名修订的 PDF 表单信息。

(顺便说一句,String 参数不是修订的名称​​,而是签名字段的名称​​,其签名签署了该修订。)

但我如何才能检索所有修订版(或至少它们的名称)?到目前为止,我还没有在 iText API 和网络中找到任何东西。

如前所述,那些修订名称实际上是签名字段名称。因此,您可以使用

List<String> names = fields.getSignatureNames()

检索可以提取修订的所有名称。

【讨论】:

  • 完美!感谢您的详细回答。这让我对这件事有了很大的了解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
  • 2022-07-14
相关资源
最近更新 更多