关闭文档书签PdfOutline例外问题

时间:2014-05-05 21:54:45

标签: itext

生成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()语句,然后是一个大纲。这就是麻烦开始的地方。当我尝试关闭文档时,我得到一个异常,我看到的是设计在close()中的PdfWriter。但是如果我们在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节是否会将内容添加到新页面?

2 个答案:

答案 0 :(得分:2)

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

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

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

如果要覆盖此而不添加内容(由mkl建议),您可以使用以下行:

writer.setPageEmpty(false);

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

答案 1 :(得分:1)

  

我们在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() 之后继续添加书签/大纲的好方法是确保在设置书签目的地后添加内容。 < / p>