微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

CopyPagesTo 复制 Field 词典错误有修复建议或仅是错误的 PDF 输入文件的结果?

如何解决CopyPagesTo 复制 Field 词典错误有修复建议或仅是错误的 PDF 输入文件的结果?

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

在对 RUPS 进行一些分析后,我注意到与 /Parent 字段字典的 /Kids 数组相关的潜在原因。 (See image of original document here) 我检查了 RUPS 使用 PdfDocument.copyPagesTo 生成文件中的类似条目 (See image of copied document here) 在该文件中 /Kids 数组是空的,根据我对 PDF 参考 1.7 的理解不应该是(它应该指向现场父母的孩子)。

我不确定 iText7 的这种功能是 iText 的错误还是原始文件的 pdf 内容错误的结果。无论如何,我试图在 iText7 中找到处理生成输出代码。我找到了处理复制 /Parent 字典的 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,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,PdfDocument todocument)
        {
            if (newField.ContainsKey(PdfName.Parent))
            {
                return;
            }
            PdfDictionary oldParent = field.GetAsDictionary(PdfName.Parent);
            if (oldParent != null)
            {
                PdfDictionary newParent = oldParent.copyTo(todocument,false);
                if (newParent.IsFlushed())
                {
                    newParent = oldParent.copyTo(todocument,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 显示 expected content of /Kids array 并且交互性在复制文档中与原始文档类似。我不得不关闭 Smartcopy 模式(如果启用它会抛出 SmartModePdfObjectsSerializer.SelfReferenceException)。对我来说,这是可以理解的,但可能是错误修复的结果。

有人可以验证 iText 中是否存在错误或 iText 运行良好但输入文件不遵循 PDF 参考吗?我也不确定(如果是错误)我的修复是否合适或仅适用于我的情况。

可以从here查看原始文件

解决方法

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

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

当我以编程方式添加缺失的 /AcroForm 字典及其指向原始文件 PDF 文件中的根字段字典的 /Fields 数组并根据 PDF 参考规范制作输入文件时,PdfDocument.CopyPagesTo 正确复制了文档和原始文件的交互性已正确转移到复制的文档中。

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

实际上,经过一些研究,我注意到使用这种格式错误的 PDF 文件(尽管文档中有 AcroForm 字段,但没有 /AcroForm 字典)调用 PdfDocument.CopyPagesTo 重载,copier 参数引用了 {{ 1}} 产生的结果与 if PdfPageFormCopier 重载 没有 PdfDocument.CopyPagesTo 参数将被调用以复制正确形成的输入文件。这意味着,当输入文件具有 Acrofields 时,在没有正确 copier 参数的情况下调用 CopyPagesTo 会生成不符合 PDF 参考的输出文件(它具有带有空 /Kids 数组的字段字典)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?