CopyPages是否复制字段字典错误(建议修复)或只是错误的PDF输入文件的结果



我正在处理一些应用程序生成的PDF文档的集合。在许多页面上,都有PDF小部件注释和一些Javascript代码,可以在页面之间进行某种导航。我尝试使用iText 7.1.14(使用PdfDocument.CopyToPages方法(合并两个这样的文档,并注意到结果文件中的交互不再起作用。为了找到问题,我试图用PdfDocument.CopyToPages只复制一个文档的一页,结果同样是错误的。

在对RUPS进行了一些分析后,我注意到了与/Parent字段字典的Kids数组有关的潜在原因。(请参阅此处原始文档的图像(我用RUPS检查了用PdfDocument.CopyPagesTo生成的文件中的类似条目(请参阅这里复制文档的图像。(在该文件中,Kids数组是空的,根据我对PDF Reference 1.7的理解,它不应该是空的(它应该指向字段父级的子级(。

我不确定iText7的这种功能是iText的错误还是原始文件pdf内容错误的结果。无论如何,我试图在iText7中查找处理生成该输出的代码。我找到了处理复制/父字典的PdfPage.RebuildFormFieldParent方法。

private void RebuildFormFieldParent(PdfDictionary field, PdfDictionary newField, PdfDocument toDocument) {
if (newField.ContainsKey(PdfName.Parent)) {
return;
}
PdfDictionary oldParent = field.GetAsDictionary(PdfName.Parent);
if (oldParent != null) {
PdfDictionary newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName
.Parent), false);
if (newParent.IsFlushed()) {
newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName.Parent), true
);
}
RebuildFormFieldParent(oldParent, newParent, toDocument);
/**** ORIGINAL CODE BELOW *****/
PdfArray kids = newParent.GetAsArray(PdfName.Kids);
if (kids == null) {
newParent.Put(PdfName.Kids, new PdfArray());
}
/******************************/
newField.Put(PdfName.Parent, newParent);
}
}

经过一些分析,我尝试在方法的末尾进行以下更改。

private void MyRebuildFormFieldParent(PdfDictionary field, PdfDictionary newField, PdfDocument toDocument)
{
if (newField.ContainsKey(PdfName.Parent))
{
return;
}
PdfDictionary oldParent = field.GetAsDictionary(PdfName.Parent);
if (oldParent != null)
{
PdfDictionary newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName
.Parent), false);
if (newParent.IsFlushed())
{
newParent = oldParent.CopyTo(toDocument, JavaUtil.ArraysAsList(PdfName.P, PdfName.Kids, PdfName.Parent), true
);
}
RebuildFormFieldParent(oldParent, newParent, toDocument);
/**** NEW CODE BELOW *****/
PdfArray kids = (PdfArray)(oldParent.GetAsArray(PdfName.Kids).CopyTo(toDocument, true));
if (kids == null)
{
newParent.Put(PdfName.Kids, new PdfArray());
}
else
{
newParent.Put(PdfName.Kids, kids);
}
/******************************/
newField.Put(PdfName.Parent, newParent);
}

在那次更改之后,我用PdfDocument.CopyPagesTo生成了文档的副本。RUPS显示了Kids数组的预期内容,并且在复制文档中的交互性与在原始文档中类似。我不得不关闭SmartCopy模式(如果启用,它会抛出SmartModePdfObjectsSerializer.SelfReferenceException(。对我来说,这在某种程度上是可以理解的,但可能是错误修复的结果。

有人能验证iText中是否存在错误吗?或者iText工作正常,但输入文件不遵循PDF参考?我也不确定(如果这是一个错误(我的修复是否合适或只适用于我的情况。

可以从这里检查原始文件。

我可以回答我自己的问题:问题出现在输入文件中,而不是iText中

输入文件格式不正确,因此pdf目录中没有/ArchoForm字典。当打开原始文件时,Adobe Acrobat Reader解释了每页中的字段,尽管PDF文件存在这种不规则性,但这种交互性仍然有效。因此,我没有怀疑有这样的问题。在用PdfDocument.CopyPagesTo复制了格式不正确的PDF文件后,字段字典的格式不正确(/Kids数组为空(,交互性也不再起作用。

当我在原始文件PDF文件中用程序添加了缺失的/ArcoForm字典及其指向根字段字典的/Fields数组,并根据PDF参考规范制作了输入文件时,PdfDocument.CopyPagesTo正确地复制了文档,原始文件的完整性正确地转移到了复制的文档中。

我使用了PdfDocument.CopyPagesTo重载,该重载使用了引用PdfPageFormCopier实例的copier参数。

事实上,经过一些研究,我注意到,对于这种格式不正确的PDF文件(尽管文档中有AcroForm字段,但没有/ArchoForm字典(,使用引用PdfPageFormCopier实例的copier参数调用PdfDocument.CopyPagesTo重载会产生与完全相同的结果,如果不使用copier参数的PdfDocument.CopyPagesTo重载会被调用以正确复制格式的输入文件。这意味着,当输入文件具有Acrofields时,在没有适当copier参数的情况下调用CopyPagesTo会生成不符合PDF Reference的输出文件(它具有空/Kids数组的字段字典(。

最新更新