简单使用Itext和Freemarker将HTML转为PDF

时间: 2023-07-29 admin 互联网

简单使用Itext和Freemarker将HTML转为PDF

简单使用Itext和Freemarker将HTML转为PDF

1、添加maven依赖

<!-- itext -->
<dependency><groupId>com.lowagie</groupId><artifactId>itext</artifactId><version>2.1.0</version>
</dependency>
<!-- renderer -->
<dependency><groupId>org.xhtmlrenderer</groupId><artifactId>core-renderer</artifactId><version>R8</version>
</dependency>
<!--freemarker-->
<dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId><version>2.3.28</version>
</dependency>
<!-- hutool 用到了模板引擎和工具类 -->
<!-- 官方文档:.html -->
<!-- 官方API文档:/ -->
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.1.0</version>
</dependency>
<!-- commons-text 用到反转义-->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-text</artifactId><version>1.8</version>
</dependency>
<!-- guava 用了一些工具方法-->
<dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>20.0</version>
</dependency>

2、准备模板文件和字体文件

  • 模板文件 demo.ftl
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"></meta><title>Title</title>
</head>
<body style = 'font-family:Microsoft YaHei;'>
<h1>PDF Demo</h1>
<h3>${user.name!'未知'}</h3>
<h3>${user.age!'未知'}</h3>
<h3>${user.gender!'未知'}</h3>
</body>
</html>
  • 字体文件 MicrosoftYaHei.ttf,百度下载一个吧,商用的话应该需授权...

3、生成PDF代码

支持中文。实际使用需注意 自定义的模板文件字体文件填充的数据,并对下方示例代码进行修改和封装。

package com.example.demo.test;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.template.Engine;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.xhtmlrenderer.pdf.ITextRenderer;import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;@Slf4j
public class Demo {//PDF保存路径public static String pdf_save_path = "/opt/demo/pdf/export/";//PDF字体路径public static String pdf_font_path = "/opt/demo/pdf/tmpl/font/MicrosoftYaHei.ttf";//模板路径public static String pdf_tmpl_path = "/opt/demo/pdf/tmpl/";//模板名称public static String pdf_tmpl_name = "demo.ftl";//PDF加密密钥public static String pdf_secret = "qwe123!@#.";public static void main(String[] args) {//读取模板Engine engine = TemplateUtil.createEngine(new TemplateConfig(pdf_tmpl_path, TemplateConfig.ResourceMode.FILE));Template template = engine.getTemplate(pdf_tmpl_name);HashMap<String, Object> data = Maps.newHashMap();//添加数据HashMap<String, Object> user = Maps.newHashMap();user.put("name","admin");user.put("age","18");user.put("gender","男");data.put("user",user);//根据模板和数据生成htmlString html = template.render(data);//对html内容进行反转义,例如将&ldquo;和&rdquo;转为双引号,防止XML解析异常html = StringEscapeUtils.unescapeHtml4(html);String fileName = "demo.pdf";try (BufferedOutputStream out = FileUtil.getOutputStream(pdf_save_path + fileName);ByteArrayOutputStream baos = new ByteArrayOutputStream()) {ITextRenderer iTextRenderer = new ITextRenderer();iTextRenderer.getFontResolver().addFont(pdf_font_path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);iTextRenderer.setDocumentFromString(html);iTextRenderer.layout();iTextRenderer.createPDF(baos);iTextRenderer.finishPDF();//添加水印(可添加多个)ArrayList<String> texts = Lists.newArrayList(DateUtil.now(), "我是水印1", "我是水印2");InputStream in = new ByteArrayInputStream(baos.toByteArray());baos.flush();addWaterMark(in, out, texts);System.out.println("success!");} catch (Exception e) {log.error("=====创建pdf异常:", e);}}/*** 添加水印** @param arr*/public static void addWaterMark(InputStream in, OutputStream out, List<String> arr) throws DocumentException, IOException {PdfReader pdfReader = new PdfReader(in);PdfStamper pdfStamper = new PdfStamper(pdfReader, out);pdfStamper.setEncryption(null, pdf_secret.getBytes(), PdfWriter.ENCRYPTION_AES_128, false);int pages = pdfReader.getNumberOfPages() + 1;// 设置水印透明度PdfGState gs = new PdfGState();gs.setFillOpacity(0.3f);for (int i = 1; i < pages; i++) {PdfContentByte underContent = pdfStamper.getOverContent(i);underContent.beginText();underContent.setFontAndSize(BaseFont.createFont(pdf_font_path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 12);underContent.setGState(gs);underContent.setColorFill(Color.blue);for (int m = 0; m < 6; m++) {for (int j = 0; j < 6; j++) {for (int n = 0; n < arr.size(); n++) {underContent.showTextAlignedKerned(Element.ALIGN_LEFT, arr.get(n), 100 * j, (n + 1) * 20 + 200 * m, 45);}}}underContent.endText();underContent.stroke();}pdfStamper.close();pdfReader.close();}
}

4、查看PDF