getFixContent
private java.util.List<IElement> getFixContent(String content) { if (content.startsWith("<div>")) { content = content.replaceAll("<div>", "<div>"); } else { content = "<div>" + content + "</div>"; } return HtmlConverter.convertToElements(content, proper); }addParagraphStyleCircle
private void addParagraphStyleCircle(Style style, java.util.List<IElement> children) { for (IElement child : children) { if (child instanceof Paragraph) { Paragraph element = (Paragraph) child; element.addStyle(style); java.util.List<IElement> children1 = element.getChildren(); this.addParagraphStyleCircle(style, children1); } if (child instanceof Div) { Div div = (Div) child; java.util.List<IElement> children1 = div.getChildren(); this.addParagraphStyleCircle(style, children1); } if (child instanceof Text) { Text text = (Text) child; text.addStyle(style); } } } 1.4.9. 监听事件在编写pdf的时候,比如一篇整体的文章,我们需要在页眉位置添加关于这篇文章的固定文本或者图形,类似于打个标签,表示你翻了这么多页一直在看这篇文章,当第二篇文章的时候就换一个,举个例子
第一页
第二页
这种需求我们如何实现呢?思路分析发现,我们需要知道什么时候文章内容一页写不起了,换了一页的时候我们需要添加一个同样的页眉。这样我们就需要知道页是何时添加的,监听事件就是处理这种问题的
pdf是PdfDocument,可添加的事件有START_PAGE,INSERT_PAGE,REMOVE_PAGE,END_PAGE共四个,如上需求我们需要监听START_PAGE事件,在事件处理中做相应的处理,我在事件中使用PdfCanvas画了头部内容
HeaderTextEvent headerTextEvent = new HeaderTextEvent(title, font); pdf.addEventHandler(PdfDocumentEvent.START_PAGE, headerTextEvent);HeaderTextEvent类,Painting仅仅是封装了PdfCanvas
public class HeaderTextEvent implements IEventHandler { private String text; private PdfFont font; public HeaderTextEvent(String text,PdfFont font) { this.text = text; this.font = font; } @Override public void handleEvent(Event event) { PdfDocumentEvent docEvent = (PdfDocumentEvent) event; PdfDocument pdfDoc = docEvent.getDocument(); Painting painting = new Painting(pdfDoc, font); painting.drawHeader(); painting.drawHeaderText(text); painting.close(); } }在添加内容前添加相应事件,同时需要记得在不需要的时候移除
// 移除监听器 pdf.removeEventHandler(PdfDocumentEvent.START_PAGE, headerTextEvent); 1.4.10. 添加目录我没有找到itext7原生是否有目录添加,根据我自己的需求,我用Table组件来实现了自定义目录,由于我的PDF是用来打印的,所以我并没有给目录添加Link,也就是页面跳转,不过当你彻底理解了我的项目,我想这个需求实现也不难
实现效果如下,随着内容的增长,目录自动增长
先说下遇到的困难,目录顾明思意,必须要有内容才会有目录,所以实际上目录是最后添加的,但如果我们添加内容到最后再跳转到前面的页面来添加目录,有三个问题:
目录有几页如何知道?
目录有几页不知道,如何知道内容在第几页?
由于目录不确定,所以后续内容的页码其实也是不确定的,也就是说页码也不是一页页可以添加过去的
而经过实践你会发现,我们不能够回到前几页去修改已存在的页面,因为会提示你已经flush了,不能修改。
这时我看到了movePage这个方法,也就是可以通过移动页面,把目录在内容之后生成,后再移动到前几页,但是页码还是不能修改,发现脑袋不够想了只能用上屁股,灵光一闪,不能一遍生成为什么不能二次渲染呢?于是研究读取原pdf在原pdf上修改,二次渲染的时候填上页码及移动页面,主要代码如下,包括了读取中间文件,移动目录,添加每页页码
PdfReader reader = null; PdfWriter writer = null; String inPath = getInPath(); try { reader = new PdfReader(new File(inPath)); writer = new PdfWriter(new File(outPath)); } catch (IOException e) { e.printStackTrace(); } PdfDocument pdf = new PdfDocument(reader, writer); Document doc = new Document(pdf); int startPage = 7; int numberOfPages = pdf.getNumberOfPages(); for (int i = 0; i < catalogSize; i++) { pdf.movePage(numberOfPages, startPage); } String forbidPage = properties.getProperty("forbidPage"); for (int pageNumber = 1; pageNumber < numberOfPages + 1; pageNumber++) { if (pageNumber > 6 + catalogSize && pageNumber != 8 + catalogSize) { if (forbidPage != null && (pageNumber - catalogSize) >= Integer.parseInt(forbidPage)) { continue; } PageSize pageSize = pdf.getDefaultPageSize(); doc.showTextAligned(new Paragraph(String.format("- %d -", pageNumber)), pageSize.getWidth() / 2, 30, pageNumber, TextAlignment.CENTER, VerticalAlignment.MIDDLE, 0); } } 1.5. 总结