实现方式: thymeleaf + jvppeteer
基于chromium实现,所见即所得,html在浏览器上什么样子,生成的PDF就是什么样子。不需要花费额外的时间调样式。
POM文件 :
<!-- springboot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>compile</scope>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.15.RELEASE</version>
</dependency>
<!-- jvppeteer -->
<dependency>
<groupId>io.github.fanyong920</groupId>
<artifactId>jvppeteer</artifactId>
<version>1.1.6</version>
</dependency>
配置文件:
server:
port: 9182
spring:
profiles:
active: @profiles.active@
thymeleaf:
#模版文件存放目录
prefix: classpath:/templates/
suffix: .html
mode: HTML
encoding: UTF-8
cache: false
puppeteer:
# 临时文件存放目录
tmp: /app/home/tmp
# chrome地址
chrome: /usr/bin/chromium-browser
核心代码:
@Autowired
private TemplateEngine templateEngine;
private String htmlGenerate(String template, JSONObject param) {
Context context = new Context();
param.forEach(context::setVariable);
//获取html文件
String htmlContent = templateEngine.process(template, context);
String tmpHtmlPath = tmpPath + "/" +UUID.randomUUID()+".html";
log.info("html临时存放目录 = {}",tmpHtmlPath);
File htmlFile = new File(tmpHtmlPath);
//1. 保存html到临时目录
try (BufferedWriter writer = new BufferedWriter(new FileWriter(htmlFile))) {
writer.write(htmlContent);
writer.flush();
} catch (IOException e) {
log.error(e.toString(),e);
log.error("保存html到临时文件失败!");
return null;
}
return tmpHtmlPath;
}
private byte[] htmlToPdf(String htmlPath) {
//生成pdf必须在无头模式下才能生效
ArrayList<String> arrayList = new ArrayList<>();
LaunchOptions options = new LaunchOptionsBuilder()
.withArgs(arrayList)
.withHeadless(true)
.withExecutablePath(chromeUrl)
.build();
arrayList.add("--no-sandbox");
arrayList.add("--disable-setuid-sandbox");
Page page = null;
Browser browser = null;
try {
browser = Puppeteer.launch(options);
page = browser.newPage();
page.goTo("file://" + htmlPath);
PDFOptions pdfOptions = new PDFOptions();
//位置
// pdfOptions.setPath("");
//大小
pdfOptions.setFormat("A4");
//边框
Margin margin = new Margin();
margin.setTop("20mm");
margin.setBottom("20mm");
pdfOptions.setMargin(margin);
//开启背景图片
pdfOptions.setPrintBackground(true);
//开启页眉页脚
pdfOptions.setDisplayHeaderFooter(true);
pdfOptions.setHeaderTemplate("<div></div>");
pdfOptions.setFooterTemplate("<div style=\"font-size: 10px; width: 100%; text-align: center; padding: 10px;\">\n" +
" 共 <span class=\"totalPages\"></span> 页,第 <span class=\"pageNumber\"></span> 页 \n" +
" </div>");
return page.pdf(pdfOptions);
} catch (InterruptedException | IOException e) {
log.error(e.getMessage(),e);
return null;
}finally {
if (page != null){
try {
page.close();
} catch (InterruptedException e) {
log.error(e.getMessage());
}
}
if (browser != null){
browser.close();
}
}
}
centos7.9 安装chromium
sudo yum install epel-release
sudo yum install https://forensics.cert.org/cert-forensics-tools-release-el7.rpm
sudo yum install chromium
安装中文字体
sudo yum install wqy-microhei-fonts