How to add HTML headers and footers to a page?

Category: 
Tags: XML WorkerXHTMLpage eventsheaderfooteriText 5

We want to add HTML headers and footers to a document. Currently, we have extended PdfPageEventHelper and overriden the onStartPage() and onEndPage() methods. This works fine for the first page, but it throws a RuntimeWorkerException when we get to 2+ pages.

 @Override
    void onStartPage(PdfWriter writer, Document document) {
        InputStream is = new ByteArrayInputStream(header?.getBytes());
        XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
    }
 
    @Override
    void onEndPage(PdfWriter writer, Document document) {
        InputStream is = new ByteArrayInputStream(footer?.getBytes());
        XMLWorkerHelper.getInstance().parseXHtml(writer, document, is);
 
    }
Posted on StackOverflow on Oct 28, 2015 by froi

It is forbidden to add content in the onStartPage() event in general. It is forbidden to add content to the document object in the onEndPage(). You should add your header and your footer in the onEndPage() method using PdfWriter, NOT document. Also: you are wasting plenty of CPU by parsing the HTML over and over again.

Please take a look at the HtmlHeaderFooter example.

It has two snippets of HTML, one for the header, one for the footer.

public static final String HEADER =
    "<table width=\"100%\" border=\"0\"><tr><td>Header</td><td align=\"right\">Some title</td></tr></table>";
public static final String FOOTER =
    "<table width=\"100%\" border=\"0\"><tr><td>Footer</td><td align=\"right\">Some title</td></tr></table>";

Note that there are better ways to describe the header and footer than by using HTML, but maybe it's one of your requirements.

We will read these HTML snippets only once in our page event and then we'll render the elements over and over again on every page:

public class HeaderFooter extends PdfPageEventHelper {
    protected ElementList header;
    protected ElementList footer;
    public HeaderFooter() throws IOException {
        header = XMLWorkerHelper.parseToElementList(HEADER, null);
        footer = XMLWorkerHelper.parseToElementList(FOOTER, null);
    }
    @Override
    public void onEndPage(PdfWriter writer, Document document) {
        try {
            ColumnText ct = new ColumnText(writer.getDirectContent());
            ct.setSimpleColumn(new Rectangle(36, 832, 559, 810));
            for (Element e : header) {
                ct.addElement(e);
            }
            ct.go();
            ct.setSimpleColumn(new Rectangle(36, 10, 559, 32));
            for (Element e : footer) {
                ct.addElement(e);
            }
            ct.go();
        } catch (DocumentException de) {
            throw new ExceptionConverter(de);
        }
    }
}

Do you see the mechanism we use to add the Element objects obtained from XML Worker? We create a ColumnText object that will write to the direct content of the writer (using the document is forbidden). We define a Rectangle and we are using go() to render the elements.

The results is shown in html_header_footer.pdf.