【问题标题】:Merging Tagged PDF without ruining the tags在不破坏标签的情况下合并标记的 PDF
【发布时间】:2013-11-07 15:10:55
【问题描述】:

我正在尝试将两个标记的 PDF 与 iTextPDF 5.4.4 版本的 jar 合并。完成所有操作后关闭文档就行了:document.close();):。它抛出以下错误

java.lang.NullPointerException
PDF Creation Failed java.lang.NullPointerException
[B@1d5c1d5c
at com.itextpdf.text.pdf.PdfCopy.fixTaggedStructure(PdfCopy.java:878)
at com.itextpdf.text.pdf.PdfCopy.flushTaggedObjects(PdfCopy.java:799)
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:836)
at com.itextpdf.text.Document.close(Document.java:416)
at PDFMerger.mergePDF(PDFMerger.java:189)

请告诉我这个问题的可能原因。

下面是我使用的代码。

PdfReader reader = new PdfReader(pdf);

boolean setTagged=reader.isTagged() ; 

Document document = new Document();

PdfCopy copy = new PdfCopy(document, new FileOutputStream("Merged.pdf"));

copy.setTagged();

document.open();

int n;
n = reader.getNumberOfPages();
for (int page = 0; page < n; ) {

    copy.addPage(copy.getImportedPage(reader, ++page,true));

}
copy.freeReader(reader);
document.close();
reader.close();

【问题讨论】:

  • 根据代码 (PdfCopy.fixTaggedStructure(PdfCopy.java:878)) iText 似乎期望在某处有一个 PG 条目,但您的源 PDF 不包含它。能否分享给大家分析一下是文档问题还是iText问题?
  • 感谢 MKL。我们想与您分享该文件以供进一步分析。你能告诉我发送它的电子邮件ID吗?
  • 我在我的 stackoverflow 配置文件描述中添加了一个地址。不过,我认为其他人也有兴趣,尤其是开发 iText 的人。除非文档不得公开,否则您可能希望通过文件共享(例如 Dropbox 或 google)而不是邮件来提供。
  • 感谢 MKL。我已将文件邮寄给您。你能看一下吗?
  • @Comm 你能把你发给 mkl 的 PDF 发给我们,以便我们测试修复吗?我已在我的个人资料中添加了一个电子邮件地址。

标签: pdf itext itextpdf merging-data


【解决方案1】:

这看起来像是当前 iText 版本中的一个错误。

@Bruno 也许有人应该调查一下这个

PdfCopy 有一个方法fixTaggedStructure 试图修复通过复制标记页面而有些乱码的标记结构。直到当前的 iText 5.4.6-SNAPSHOT 包括在内,您都可以找到以下代码

PdfDictionary dict = (PdfDictionary)iobj.object;
PdfIndirectReference pg = (PdfIndirectReference)dict.get(PdfName.PG);
//if pg is real page - do nothing, else set correct pg and remove first MCID if exists
if (!pageReferences.contains(pg) && !pg.equals(currPage)){
    dict.put(PdfName.PG, currPage);
    PdfArray kids = dict.getAsArray(PdfName.K);
    if (kids != null) {
        PdfObject firstKid = kids.getDirectObject(0);
        if (firstKid.isNumber()) kids.remove(0);
    }
}

对于某个数组中的 StructElem 标记元素 dict。此代码通过执行pg.equals(currPage) 隐含地假定该字典dict 中有一个键PdfName.PG 的条目。不幸的是,该条目是可选的,例如OP 提供的示例文档包含从某个数组引用的此类 StructElem 字典,而没有 Pg 条目。这会导致有问题的 NPE。

在这种情况下,只需更改 equals 调用中的顺序即可,即代替

if (!pageReferences.contains(pg) && !pg.equals(currPage)){

应该使用

if (!pageReferences.contains(pg) && !currPage.equals(pg)){

if (pg != null && !pageReferences.contains(pg) && !pg.equals(currPage)){

取决于这里的实际程序逻辑。

@Bruno 请检查哪个变体在语义上是正确的;毕竟我并不是很喜欢这种标记结构的东西......

【讨论】:

  • 由于某种原因,我在 11 月错过了这个问题。我现在在纽约,参加了第二天的 ISO 委员会会议(今天我们连续讨论了 9 个多小时的 PDF)。我还有两天要去。我将参考这个问题在我们的付费票务系统中创建一张票。一旦我们的支持工程师解决了这个问题,Raf Hens 或我自己就会在此处发布消息。
  • @Comm,该修复已添加到我们的开发版本中。它将包含在下一个版本中。如果需要,您已经可以从我们在 Sourceforge 上的 SVN 存储库构建。
  • @rhens,谢谢。你能告诉我们下一个版本是什么时候吗?
  • @Comm,我预计会在 1 月底、2 月中旬左右。
  • @rhens,谢谢。我们在 svn repo 中构建了 5.4.6 jar,现在它工作正常。请让我们知道它何时发布,以便我们继续使用它。
【解决方案2】:

代码是用 C# 编写的

  public static byte[] mergeTest(byte[] pdf) {
        PdfReader reader = null;
        Document doc = null;
        PdfCopy copy = null;
        MemoryStream stream = new MemoryStream();
        byte[] output = null;

        try {
            reader = new PdfReader(pdf);
            doc = new Document();

            copy = new PdfCopy(doc, stream);
            bool tagged = reader.IsTagged();

            if (tagged)
                copy.SetTagged();


            doc.Open();

            for (int x = 1; x <= reader.NumberOfPages; x++) {
                copy.AddPage(copy.GetImportedPage(reader, x, tagged));
            }

            copy.FreeReader(reader);
            doc.Close();
            copy.Close();

            output = stream.ToArray();

            stream.Flush();
            stream.Dispose();

        } catch (Exception ex) {

        } finally {
            try {
                if (reader != null)
                    reader.Close();
            } catch (Exception) { }
        }
        return output;
    }

【讨论】:

  • 嗨 Capiono,感谢您的 cmets。即使在基于原始文档设置此标签后,我们也面临同样的问题。我们想知道 itextpdf jar 在 com.itextpdf.text.pdf.PdfCopy.fixTaggedStructure(PdfCopy.java:878) 的这一行检查了什么,以便我们可以找到原始标记的 pdf 是否具有正确的结构。跨度>
  • 好的,我现在看到了这个错误。在我升级到最新版本 5.4.4.0 后开始。我与 Itext 进行了交谈,他们知道这件事并正在解决问题。他们我们在月底有一个新版本。
  • 感谢 Capiono。我什至使用 5.4.0 和 5.4.2 版本进行了测试,得到了同样的错误。您能否告诉我们这个错误是否存在于处理标记 pdf 的所有 itextpdf 版本中,或者只有 5.4.4 版本存在这个问题。
  • 我们仍然面临这个问题。任何人都可以帮助我们提供信息。
  • 新库/jar 已经发布,应该包含此问题的修复程序。
猜你喜欢
  • 2013-08-21
  • 2014-07-29
  • 2021-12-31
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多