当前位置: 首页 > 知识库问答 >
问题:

iText 7-最后一页的不同页脚-PdfDictionary中的空指针

东郭阳德
2023-03-14

我试图在itext7中实现页脚,文档最后一页的页脚应该不同,我添加了一个事件处理程序,当文档关闭时调用该处理程序,但试图在页面上循环会导致空指针异常:

java.lang.NullPointerException
at com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:482)
at com.itextpdf.kernel.pdf.PdfDictionary.get(PdfDictionary.java:152)
at com.itextpdf.kernel.pdf.PdfPage.newContentStream(PdfPage.java:777)
at com.itextpdf.kernel.pdf.PdfPage.newContentStreamBefore(PdfPage.java:212)

下面是我试图实现的代码:

private void onCloseDocument(
        final PdfDocument document, final float xpos, final float ypos)
{

    for (int i = 1; i <= document.getPdfDocument().getNumberOfPages(); i++)
    {
        final PdfPage page = document.getPdfDocument().getPage(i);
        final PdfCanvas canvas =
                new PdfCanvas(page.newContentStreamBefore(), page.getResources(), document.getPdfDocument());
        canvas.beginText();
        canvas.setFontAndSize(document.getFont(), FONT_SIZE);
        canvas.setLeading(14.4F);

        canvas.moveText(xpos, ypos);

        if (i == document.getPdfDocument().getNumberOfPages())
        {
            canvas.showText("Last page");
        }
        else
        {
            canvas.showText("Another page");
        }

        canvas.endText();
        canvas.stroke();
        canvas.release();
    }
}

最初,我认为这是有效的,因为我插入了一个单独的区域中断,以使pdf在两个页面上分裂,但是当我添加更多的内容和页面自然增加时,我得到了这个异常,类似地,我现在通过尝试插入多个区域中断进行测试,我得到了相同的异常。

共有1个答案

欧阳绪
2023-03-14

正如你自己发现的,

如果在创建文档时将immediateflush设置为false,则不会出现此问题。

原因是itext通常试图将数据写入输出流,并尽可能早地释放内存,以避免留下太大的内存占用。因此,您的方法

另一种方法是使用普通的end_page事件侦听器模式。您可以给这样一个事件侦听器一些方法来通知它哪一页将是最后一页。当事件侦听器被触发时,它可以检查它当前是否正在处理该页面,在这种情况下,它可以绘制一个替代的页脚,例如,如下所示:

class TextFooterEventHandler implements IEventHandler {
    Document doc;
    PdfPage lastPage = null;

    public TextFooterEventHandler(Document doc) {
        this.doc = doc;
    }

    @Override
    public void handleEvent(Event event) {
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfCanvas canvas = new PdfCanvas(docEvent.getPage());
        Rectangle pageSize = docEvent.getPage().getPageSize();
        canvas.beginText();
        try {
            canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA_OBLIQUE), 5);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (lastPage == docEvent.getPage()) {
            canvas.moveText((pageSize.getRight() - doc.getRightMargin() - (pageSize.getLeft() + doc.getLeftMargin())) / 2 + doc.getLeftMargin(), pageSize.getTop() - doc.getTopMargin() + 10)
                .showText("VERY SPAECIAL LAST PAGE HEADER")
                .moveText(0, (pageSize.getBottom() + doc.getBottomMargin()) - (pageSize.getTop() - doc.getTopMargin()) - 20)
                .showText("VERY SPAECIAL LAST PAGE FOOTER")
                .endText()
                .release();
        } else {
            canvas.moveText((pageSize.getRight() - doc.getRightMargin() - (pageSize.getLeft() + doc.getLeftMargin())) / 2 + doc.getLeftMargin(), pageSize.getTop() - doc.getTopMargin() + 10)
                .showText("this is a header")
                .moveText(0, (pageSize.getBottom() + doc.getBottomMargin()) - (pageSize.getTop() - doc.getTopMargin()) - 20)
                .showText("this is a footer")
                .endText()
                .release();
        }
    }
}    

(CreateSpecificFooters中的内部类)

您可以这样使用它:

java prettyprint-override">PdfDocument pdfDoc = new PdfDocument(new PdfWriter(new File("differentLastPageFooter.pdf")));
Document doc = new Document(pdfDoc);
TextFooterEventHandler eventHandler = new TextFooterEventHandler(doc);
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, eventHandler);
for (int i = 0; i < 12; i++) {
    doc.add(new Paragraph("Test " + i + " 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."));
}

// the currently last page is also the last page of the document, so inform the event listener 
eventHandler.lastPage = pdfDoc.getLastPage();
doc.close();
 类似资料:
  • 我通过从Listview中删除默认分隔符来设置我的自定义分隔符: 并在(保留项目图标;保留项目文本): 正因为如此,我在每个项目文本下都有客户分隔符(视图),但在项目图标下没有。 在列表中的最后一项之后,我希望分割符也可以在这样的图标下显示: 以下是通货膨胀的原因:

  • 问题内容: 我有一个客户想打印的网页,而我遇到的麻烦是让页脚位于最后一个打印页面的底部,而不仅仅是内容结束时 我尝试了类似的东西 但它在每页末尾显示页脚。 也许我对CSS的要求太高了…可行吗? 我想我应该对 的(^_^)发疯 问题答案: 尝试将相对的身体和绝对的页脚定位: 借助CSS 3 Paged Media模块,您可以使用以下代码:

  • 我在运行时用一个模板文件在itext7.pdfhtml中构建一个PDF。我想在生成的PDF中的每一页都添加一个页脚,该PDF有两页,但出于某种原因,页脚只出现在第二页。

  • 我试图创建一个带有页眉和页脚的PDF。页眉和页脚都是图像。由于我的pdf创建了随机数量的页面,我需要自动将其添加到每一页。我知道我需要使用某种eventhandler。不幸的是,我找不到vb.net语言中的任何示例,我只能找到java/C#示例,我真的不擅长阅读/转换这些语言vb.net.我还不是编程专家。 谁能给我指一下正确的方向吗。 Edit4:删除的随机内容不再需要回答我的问题。 下面这段代

  • 我只想在第一页和最后一页打印页脚。我怎样才能做到这一点?

  • 我需要启用3种页眉类型的报告:“第一页页眉”,“中间页页眉”和“最后一页页眉”。所有这些标头可以具有不同数量的报表元素,并且位于不同的位置。页脚也一样。 注意:报表必须在其频段中支持jr:table或jr:list等报表元素。这些元素必须通过xml数据源与数据一起提供。 我能够通过使用band来模拟第一页标题,但在启用“中间页标题”和“最后页标题”时遇到了问题。这就是我要做的: 有没有办法检查当前