使用IText7 把html 转PDF 并且增加页脚

发布时间 2023-07-14 08:10:45作者: HJ.Steven
itext7 对于pdf的编辑功能还是很不错的,就是文档太少了。官方提供的文档也是介绍案例的方式,如何去使用 itext ,一些定制化需求就需要去摸索 。
最近我的项目上就遇到需要在通过html 转换之后的pdf上增加页脚这样的需求 ,啃官方文档研究和自己不断尝试终于解决了问题。
为了能帮助到有相同需求的其他人,分享下我的解决方案。
我是王徽军,一个热衷于Java开发的高级开发工程师,关注我,了解更多中间件的使用技巧 。

首先引用itext的依赖

因为我是使用html转pdf的功能,所以直接引用的是 html2pdf这个依赖

<dependency>
	<groupId>com.itextpdf</groupId>
	<artifactId>html2pdf</artifactId>
	<version>5.0.0</version>
</dependency>

这个依赖会包含核心的功能

实现的核心思路

添加页脚的思路很简单,官方文档的案例也有 就是通过添加事件驱动的方式去完成。

PdfWriter pdfWriter = new PdfWriter(out);
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
PageFootEventHandler pageFootEventHandler = new PageFootEventHandler(doc, footIElements);
pdfDocument.addEventHandler(PdfDocumentEvent.INSERT_PAGE,pageFootEventHandler);

添加事件的方法第一个参数是 事件执行的时机,INSERT_PAGE 就是在插入新的页面的时候执行,第二个参数就是继承了IEventHandler 这个类的实现类的对象,这个实现类就需要实现一个接口方法我们想要的工作

public class PageFootEventHandler implements IEventHandler {

    private Document document;

    private List<IElement> iElements;

    @Override
    public void handleEvent(Event event) {
        document.setBottomMargin(130);
        PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
        PdfPage page = docEvent.getPage();
        //通过 page 进行一些处理  ,这个需要去了解如何在page上进行添加内容
        //也可以传入  List<IElement> iElements ,直接添加 ,

        Rectangle pageSize = page.getPageSize();
        PdfCanvas pdfCanvas = new PdfCanvas(page);
        float pageWith = pageSize.getWidth();
        float footHeight = 120;
        float marginWith = 20;
        float marginBottom = 20;

        Rectangle rectangle = new Rectangle(marginWith,marginBottom,pageWith-marginWith*2,footHeight-marginBottom);
        Canvas canvas = new Canvas(pdfCanvas,rectangle);
        iElements.forEach(item -> {
            canvas.add((IBlockElement) item);
        });
        pdfCanvas.release();
    }
}

到这里就是主要的一个思路 ,可能没有特殊的需求的人都能实现页脚的处理
但是我的需求里面页脚的高度还是有点高的,如果不处理,就会导致页脚的部分内容和页面内容重合在一起了 。所以要设置一下每页的内容的margin。但是官网给的设置margin 不能设置每页的margin 。pdfPage 也没有这个方法 。设置margin 只有 documentdocument.setBottomMargin(130) 这个方法。这个方法呢只会在整个文档底部有一个margin,不是每一页都能设置 。后来从别人那里 借鉴到一个思路,就是 在插入新的一页的时候,都设置一下这个margin 。我尝试了一下确实实现了。这就是为什么我的 PageFootEventHandler 里面也传入了 Document 对象。

html转pdf如何获取到Document

如果使用 HtmlConverter.convertToPdf()方法的话,你连document都见不到 。那就换一个方法。使用 HtmlConverter.convertToDocument()这个方法是能获取到document ,但是这个时候他已经完成了页面的转换,也就是说已经生成了pdf ,也没办法对每一页进行设置margin 。最后还好有这个方法

public static List<IElement> convertToElements(InputStream htmlStream) throws IOException 

我为了方便只写了一部分,具体内容可以自己看源码 。返回的元素列表就不是document ,然后我们自己创建一个document,把这个元素列表添加进去 ,就可以了 。如下是我的实现代码部分 。

Document doc = new Document(pdfDocument);
List<IElement> iElements = HtmlConverter.convertToElements(inputStream, properties);
PageFootEventHandler pageFootEventHandler = new PageFootEventHandler(doc, footIElements);
pdfDocument.addEventHandler(PdfDocumentEvent.INSERT_PAGE,pageFootEventHandler);
pdfDocument.setDefaultPageSize(PageSize.A4);
for(IElement iElement : iElements){
    doc.add((IBlockElement) iElement);
}
pdfDocument.removeEventHandler(PdfDocumentEvent.INSERT_PAGE,pageFootEventHandler);

这个代码不是完整的代码,直接运行肯定不行,这个代码只是提供了一个思路 。具体需要结合自己的业务去构造缺失的部分对象 。

好了关于 html 转 pdf 后需要添加页脚的需求已经讲完了,我是王徽军,关注我,带你了解更多技术难题的解决思路。