PdfPageEvent 接口
onOpenDocument():当文档打开后触发,初始化变量整个文档可使用
onStartPage():当开始一个新页面触发,初始化页面级变量,不要在这个方法内添加内容
onEndPage():开始一个新页面并在文档关闭前触发,这里添加header、footer、watermark等
onCloseDocument():文档关闭时触发,这里释放资源

- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.sql.SQLException;
- import com.itextpdf.text.Chapter;
- import com.itextpdf.text.Document;
- import com.itextpdf.text.DocumentException;
- import com.itextpdf.text.Element;
- import com.itextpdf.text.Font;
- import com.itextpdf.text.PageSize;
- import com.itextpdf.text.Paragraph;
- import com.itextpdf.text.Phrase;
- import com.itextpdf.text.Rectangle;
- import com.itextpdf.text.Font.FontFamily;
- import com.itextpdf.text.pdf.ColumnText;
- import com.itextpdf.text.pdf.PdfPageEventHelper;
- import com.itextpdf.text.pdf.PdfWriter;
-
- public class MovieHistory2 {
-
- /** The resulting PDF file. */
- public static final String RESULT
- = "results/part1/chapter05/movie_history2.pdf";
-
- /** Inner class to add a header and a footer. */
- class HeaderFooter extends PdfPageEventHelper {
- /** Alternating phrase for the header. */
- Phrase[] header = new Phrase[2];
- /** Current page number (will be reset for every chapter). */
- int pagenumber;
-
- /**
- * Initialize one of the headers.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onOpenDocument(PdfWriter writer, Document document) {
- header[0] = new Phrase("Movie history");
- }
-
- /**
- * Initialize one of the headers, based on the chapter title;
- * reset the page number.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onChapter(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document, float,
- * com.itextpdf.text.Paragraph)
- */
- public void onChapter(PdfWriter writer, Document document,
- float paragraphPosition, Paragraph title) {
- header[1] = new Phrase(title.getContent());
- pagenumber = 1;
- }
-
- /**
- * Increase the page number.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onStartPage(PdfWriter writer, Document document) {
- pagenumber++;
- }
-
- /**
- * Adds the header and the footer.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onEndPage(PdfWriter writer, Document document) {
- Rectangle rect = writer.getBoxSize("art");
- switch(writer.getPageNumber() % 2) {
- case 0:
- ColumnText.showTextAligned(writer.getDirectContent(),
- Element.ALIGN_RIGHT, header[0],
- rect.getRight(), rect.getTop(), 0);
- break;
- case 1:
- ColumnText.showTextAligned(writer.getDirectContent(),
- Element.ALIGN_LEFT, header[1],
- rect.getLeft(), rect.getTop(), 0);
- break;
- }
- ColumnText.showTextAligned(writer.getDirectContent(),
- Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)),
- (rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
- }
- }
-
- /** The different epochs. */
- public static final String[] EPOCH =
- { "Forties", "Fifties", "Sixties", "Seventies", "Eighties",
- "Nineties", "Twenty-first Century" };
- /** The fonts for the title. */
- public static final Font[] FONT = new Font[4];
- static {
- FONT[0] = new Font(FontFamily.HELVETICA, 24);
- FONT[1] = new Font(FontFamily.HELVETICA, 18);
- FONT[2] = new Font(FontFamily.HELVETICA, 14);
- FONT[3] = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
- }
-
- /**
- * Creates a PDF document.
- * @param filename the path to the new PDF document
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public void createPdf(String filename)
- throws IOException, DocumentException, SQLException {
- // step 1
- Document document = new Document(PageSize.A4, 36, 36, 54, 54);
- // step 2
- PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
- HeaderFooter event = new HeaderFooter();
- writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
- writer.setPageEvent(event);
- // step 3
- document.open();
- // step 4
- Chapter chapter = null;
- // 初始化数据...
- document.add(chapter);
- // step 5
- document.close();
- }
-
- /**
- * Main method.
- *
- * @param args no arguments needed
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public static void main(String[] args)
- throws IOException, DocumentException, SQLException {
- new MovieHistory2().createPdf(RESULT);
- }
- }
利用XObject特性,iText 真正将PdfTemplate 写入 OutputStream 是在调用releaseTemplate() 时。

- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.sql.SQLException;
- import com.itextpdf.text.Document;
- import com.itextpdf.text.DocumentException;
- import com.itextpdf.text.Element;
- import com.itextpdf.text.ExceptionConverter;
- import com.itextpdf.text.Image;
- import com.itextpdf.text.PageSize;
- import com.itextpdf.text.Phrase;
- import com.itextpdf.text.Rectangle;
- import com.itextpdf.text.pdf.ColumnText;
- import com.itextpdf.text.pdf.PdfPCell;
- import com.itextpdf.text.pdf.PdfPTable;
- import com.itextpdf.text.pdf.PdfPageEventHelper;
- import com.itextpdf.text.pdf.PdfTemplate;
- import com.itextpdf.text.pdf.PdfWriter;
-
- public class MovieCountries1 {
-
- /** The resulting PDF file. */
- public static final String RESULT
- = "D:/data/iText/inAction/chapter05/movie_countries1.pdf";
-
- /**
- * Inner class to add a table as header.
- */
- class TableHeader extends PdfPageEventHelper {
- /** The header text. */
- String header;
- /** The template with the total number of pages. */
- PdfTemplate total;
-
- /**
- * Allows us to change the content of the header.
- * @param header The new header String
- */
- public void setHeader(String header) {
- this.header = header;
- }
-
- /**
- * Creates the PdfTemplate that will hold the total number of pages.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onOpenDocument(PdfWriter writer, Document document) {
- total = writer.getDirectContent().createTemplate(30, 16);
- }
-
- /**
- * Adds a header to every page
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onEndPage(PdfWriter writer, Document document) {
- PdfPTable table = new PdfPTable(3);
- try {
- table.setWidths(new int[]{24, 24, 2});
- table.setTotalWidth(527);
- table.setLockedWidth(true);
- table.getDefaultCell().setFixedHeight(20);
- table.getDefaultCell().setBorder(Rectangle.BOTTOM);
- table.addCell(header);
- table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_RIGHT);
- table.addCell(String.format("Page %d of", writer.getPageNumber()));
- PdfPCell cell = new PdfPCell(Image.getInstance(total));
- cell.setBorder(Rectangle.BOTTOM);
- table.addCell(cell);
- table.writeSelectedRows(0, -1, 34, 803, writer.getDirectContent());
- }
- catch(DocumentException de) {
- throw new ExceptionConverter(de);
- }
- }
-
- /**
- * Fills out the total number of pages before the document is closed.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onCloseDocument(PdfWriter writer, Document document) {
- ColumnText.showTextAligned(total, Element.ALIGN_LEFT,
- new Phrase(String.valueOf(writer.getPageNumber() - 1)),
- 2, 2, 0);
- }
- }
-
- /**
- * Creates a PDF document.
- * @param filename the path to the new PDF document
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public void createPdf(String filename)
- throws IOException, DocumentException, SQLException {
- // step 1
- Document document = new Document(PageSize.A4, 36, 36, 54, 36);
- // step 2
- PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
- TableHeader event = new TableHeader();
- writer.setPageEvent(event);
- // step 3
- document.open();
- // step 4
- // 新建页面数据...
- document.add(new Phrase("Hello Page 1."));
- document.newPage();
- document.add(new Phrase("Hello Page 2."));
- document.newPage();
- document.add(new Phrase("Hello Page 3."));
- document.newPage();
- document.add(new Phrase("Hello Page 4."));
- // step 4
- document.close();
- }
-
- /**
- * Main method.
- *
- * @param args no arguments needed
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public static void main(String[] args)
- throws IOException, DocumentException, SQLException {
- new MovieCountries1().createPdf(RESULT);
- }
- }
在页尾添加页码

- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.sql.SQLException;
- import com.itextpdf.text.Document;
- import com.itextpdf.text.DocumentException;
- import com.itextpdf.text.ExceptionConverter;
- import com.itextpdf.text.PageSize;
- import com.itextpdf.text.Phrase;
- import com.itextpdf.text.pdf.BaseFont;
- import com.itextpdf.text.pdf.PdfContentByte;
- import com.itextpdf.text.pdf.PdfPageEventHelper;
- import com.itextpdf.text.pdf.PdfTemplate;
- import com.itextpdf.text.pdf.PdfWriter;
-
- /**
- * TODO 在此写上类的相关说明.
- * @author gongqiang
- * @version 1.0.0 2023年9月18日
- * @see
- * @since JDK 1.5.0
- */
- public class MovieCountries {
-
- /** The resulting PDF file. */
- public static final String RESULT
- = "D:/data/iText/inAction/chapter05/movie_countries.pdf";
-
- /**
- * Inner class to add a table as header.
- */
- class TableHeader extends PdfPageEventHelper {
- /** The header text. */
- String header;
- /** The template with the total number of pages. */
- PdfTemplate total;
-
- BaseFont baseFont;
-
- int fontSize = 14;
- /**
- * Allows us to change the content of the header.
- * @param header The new header String
- */
- public void setHeader(String header) {
- this.header = header;
- }
-
- /**
- * Creates the PdfTemplate that will hold the total number of pages.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onOpenDocument(PdfWriter writer, Document document) {
- total = writer.getDirectContent().createTemplate(30, 16);
- try {
- baseFont = BaseFont.createFont("D:/data/iText/fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
- } catch (Exception e) {
- throw new ExceptionConverter(e);
- }
- }
-
- /**
- * Adds a header to every page
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onEndPage(PdfWriter writer, Document document) {
- // 新建获得用户页面文本和图片内容位置的对象
- PdfContentByte pdfContentByte = writer.getDirectContent();
- // 保存图形状态
- pdfContentByte.saveState();
- String text = "页" + writer.getPageNumber() + "/";
- //String text = "页 99/";
- // 获取点字符串的宽度
- float textSize = baseFont.getWidthPoint(text, fontSize);
- pdfContentByte.beginText();
- // 设置随后的文本内容写作的字体和字号
- pdfContentByte.setFontAndSize(baseFont, fontSize);
-
- // 定位'X/'
- // float x = (document.right() + document.left()) / 2;
- float x = document.right() - 50;
- float y = 20f;
- pdfContentByte.setTextMatrix(x, y);
- pdfContentByte.showText(text);
- pdfContentByte.endText();
-
- // 将模板加入到内容(content)中- // 定位'Y'
- pdfContentByte.addTemplate(total, x + textSize, y);
-
- pdfContentByte.restoreState();
- }
-
- /**
- * Fills out the total number of pages before the document is closed.
- * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(
- * com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
- */
- public void onCloseDocument(PdfWriter writer, Document document) {
- total.beginText();
- total.setFontAndSize(baseFont, fontSize);
- total.setTextMatrix(0, 0);
- // 设置总页数的值到模板上,并应用到每个界面
- total.showText(String.valueOf(writer.getPageNumber()));
- //total.showText(String.valueOf("99"));
- total.endText();
- }
- }
-
- /**
- * Creates a PDF document.
- * @param filename the path to the new PDF document
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public void createPdf(String filename)
- throws IOException, DocumentException, SQLException {
- // step 1
- Document document = new Document(PageSize.A4, 36, 36, 54, 36);
- // step 2
- PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
- TableHeader event = new TableHeader();
- writer.setPageEvent(event);
- // step 3
- document.open();
- // step 4
- // 新建页面数据...
- document.add(new Phrase("Hello Page 1."));
- document.newPage();
- document.add(new Phrase("Hello Page 2."));
- document.newPage();
- document.add(new Phrase("Hello Page 3."));
- document.newPage();
- document.add(new Phrase("Hello Page 4."));
- // step 4
- document.close();
- }
-
- /**
- * Main method.
- *
- * @param args no arguments needed
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public static void main(String[] args)
- throws IOException, DocumentException, SQLException {
- new MovieCountries().createPdf(RESULT);
- }
- }
如果水印是图片,可以通过PdfContentByte.addImage()、或将图片包装成ColumnText对象,或者添加到表格的cell里。
注意:Image对象需要在onOpenDocument()方法内初始化,避免重复添加图片的字节流。

- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.sql.SQLException;
- import com.itextpdf.text.Document;
- import com.itextpdf.text.DocumentException;
- import com.itextpdf.text.Element;
- import com.itextpdf.text.Font;
- import com.itextpdf.text.Font.FontFamily;
- import com.itextpdf.text.PageSize;
- import com.itextpdf.text.Phrase;
- import com.itextpdf.text.pdf.ColumnText;
- import com.itextpdf.text.pdf.GrayColor;
- import com.itextpdf.text.pdf.PdfPageEventHelper;
- import com.itextpdf.text.pdf.PdfWriter;
-
- public class MovieCountries2 extends MovieCountries1 {
-
- /** The resulting PDF file. */
- public static final String RESULT
- = "D:/data/iText/inAction/chapter05/movie_countries2.pdf";
-
- /**
- * Inner class to add a watermark to every page.
- */
- class Watermark extends PdfPageEventHelper {
-
- Font FONT = new Font(FontFamily.HELVETICA, 52, Font.BOLD, new GrayColor(0.75f));
-
- public void onEndPage(PdfWriter writer, Document document) {
- ColumnText.showTextAligned(writer.getDirectContentUnder(),
- Element.ALIGN_CENTER, new Phrase("FOOBAR FILM FESTIVAL", FONT),
- 297.5f, 421, writer.getPageNumber() % 2 == 1 ? 45 : -45);
- }
- }
-
- /**
- * Creates a PDF document.
- * @param filename the path to the new PDF document
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public void createPdf(String filename)
- throws IOException, DocumentException, SQLException {
- // step 1
- Document document = new Document(PageSize.A4, 36, 36, 54, 36);
- // step 2
- PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(RESULT));
- TableHeader event = new TableHeader();
- writer.setPageEvent(event);
- writer.setPageEvent(new Watermark());
- // step 3
- document.open();
- // step 4
- // 新建页面数据...
- document.add(new Phrase("Hello Page 1."));
- document.newPage();
- document.add(new Phrase("Hello Page 2."));
- document.newPage();
- document.add(new Phrase("Hello Page 3."));
- document.newPage();
- document.add(new Phrase("Hello Page 4."));
- // step 5
- document.close();
- }
-
- /**
- * Main method.
- *
- * @param args no arguments needed
- * @throws DocumentException
- * @throws IOException
- * @throws SQLException
- */
- public static void main(String[] args)
- throws IOException, DocumentException, SQLException {
- new MovieCountries2().createPdf(RESULT);
- }
- }