【问题标题】:Bookmark PdfOutline Exception Issue on Close of Document关闭文档时添加书签 PdfOutline 异常问题
【发布时间】:2014-05-05 21:54:45
【问题描述】:

我在生成 PDF 时遇到了一个有趣的问题。我最近在 PDF 中引入了书签,并在关闭文档时发现了一些问题。让我们从正在发生的事情的示例代码开始。

private static String CONTENT = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.\n" +
        "\n" +
        "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.\n" +
        "\n" +
        "Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n" +
        "\n" +
        "Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.\n" +
        "\n" +
        "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis.\n" +
        "\n" +
        "At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.\n";

public static void main(String[] args)
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    Document document = new Document();
    try
    {
        PdfWriter writer = PdfWriter.getInstance(document, baos);
        document.open();
        PdfOutline root = writer.getRootOutline();

        int i = 0;
        PdfDestination destination = new PdfDestination(PdfDestination.XYZ);
        PdfOutline outline = new PdfOutline(root, destination, "Section 1");
        writer.getDirectContent().localDestination(""+(i++), destination);
        document.add(new Paragraph(CONTENT));

        document.newPage();

        destination = new PdfDestination(PdfDestination.XYZ);
        outline = new PdfOutline(root, destination, "Section 2");
        writer.getDirectContent().localDestination(""+(i++), destination);

        document.close();

        PDFEmbeddedManager manager = new PDFEmbeddedManager();

        JFrame frame = new JFrame("TEST");
        frame.setSize(1024, 768);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(manager.getFormView(), BorderLayout.CENTER);


        manager.showPDF(baos.toByteArray(), "");

        frame.setVisible(true);
    }
    catch (DocumentException e)
    {
        e.printStackTrace();
    }
}

在我们将 CONTENT 添加到文档之后,您会注意到一个 newPage() 语句,然后是一个大纲。这就是麻烦开始的地方。当我尝试关闭文档时,我们得到一个异常,我看到这是 PdfWriter 的 close() 中的设计。但是如果我们在 newPage() 之后删除书签,一切都很好,也不例外。

现在我的问题是,我们在 newPage() 之后继续添加书签/大纲的好方法是什么,这将允许我们毫无例外地关闭文档?有没有办法让我们浏览所有书签/大纲,将它们的目的地固定为指向最后一页而不是不存在的页面?非常感谢任何帮助和见解。谢谢!

编辑:

这是一个例外:

Exception in thread "main" java.lang.RuntimeException: The page 2 was requested but the document has only 1 pages.

编辑 2:

主要是,我想要实现的是在书签中显示第 2 节,即使第 2 节有内容与否。由于在第 1 节末尾调用 newPage(),然后添加第 2 节大纲但不添加内容,因此引发异常。有什么办法让我仍然添加第 2 节大纲/书签,而不必担心第 2 节是否会将内容添加到新页面?

【问题讨论】:

    标签: itext


    【解决方案1】:

    我打算更新 mkl 的答案,但最后我决定添加一个额外的答案,因为这个问题有一个非常具体的原因需要澄清。

    您的异常告诉您您正在尝试链接到第 2 页,但该文档只有一页。为什么你的文档只有一页?

    当您触发document.newPage() 时,仅当当前页面不为空白时才会创建新页面。这是设计使然,因为newPage() 也是由 iText 在内部触发的,过去的经验告诉我们,这通常会导致不需要的空白页。

    如果你想覆盖这个而不添加内容(如mkl所建议的那样),你可以使用以下行:

    writer.setPageEmpty(false);
    

    创建新页面时,pageEmpty 的标志为 true,直到您添加内容。您可以使用setPageEmpty() 方法将此标志设置为false。如果这样做,您的文档将超过 1 页。请参阅NewPage 示例以了解该机制的工作原理。

    【讨论】:

    • 我们在 PDF 中添加了许多部分;有些部分可能不会添加,而其他部分可能会添加。每个部分都以 newPage() 结束,以准备下一部分。基本上,我们的问题是我们希望看到一个书签,它应该在一个部分的位置上,无论它是否添加了任何内容,并且在处理一个部分之前首先添加大纲。例如,将 A 部分的 Ouline 及其内容添加到 PDF 和 newPage()。 B节大纲添加但没有内容,关闭文档->异常。关于我们能做什么的任何想法?我们希望看到 B 部分的书签。
    • 另外,我希望将 setPageEmpty() 设置为 true,因为多个部分可能会在不添加单个内容的情况下连续调用 newPage()。
    • 另外,我希望将 setPageEmpty() 设置为 true - 在这种情况下,请确保在设置最终目的地后添加内容,参见。我的回答,例如带有居中“结尾”的最后一页。或者仅在文档末尾,关闭之前使用 setPageEmpty 技巧。
    【解决方案2】:

    什么是我们在 newPage() 之后继续添加书签/大纲的好方法,这将允许我们毫无例外地关闭文档?

    newPage() 之后使用大纲不足以触发您的问题。重要的是您不要在 newPage() 之后添加任何内容,只添加书签。

    会发生以下情况:

    • newPage() 使 iText 完成当前(第一)页并在内存中开始新的(第二)页。
    • localDestination(...) 将目标初始化为指向当前页面 2。
    • close(),当前页面 2 上仍然没有内容,因此不会写入 PDF。
    • close() 中编写书签时,iText 看到一个不存在的页面上有一个书签目标并引发异常。

    您可以通过在设置目的地后向文档添加内容来轻松防止该异常的发生,例如

        ...
        writer.getDirectContent().localDestination(""+(i++), destination);
        document.add(new Paragraph("x")); // <<<<< Adds content to the page the destination points to
    
        document.close();
    

    工作得很好。

    因此,newPage() 之后继续添加书签/大纲的好方法是确保在设置书签目标后添加内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多