Java实现html填充导出pdf
1.依赖添加和pom修改
<!-- Thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- OpenPDF 库 -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.29</version>
</dependency>
<!-- HTML转PDF工具(flying-saucer) -->
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.20</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf-openpdf</artifactId>
<version>9.1.20</version>
</dependency>
为了解决:java.io.IOException: /app/idmp-datam-job.jar!/BOOT-INF/classes!/fonts/SimSun.ttf not found as file or resource.
<resources>
<resource>
<directory>src/main/resources</directory>
<!--开启过滤,用指定的参数替换directory下的文件中的参数-->
<filtering>true</filtering>
<excludes>
<exclude>fonts/</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>fonts/</include>
</includes>
</resource>
</resources>
2.工具类
操作过程主要出现问题的地方在于字体的问题,字体放在resource/fonts目录下。
第一次运行的时候将文件复制出来然后每次执行就读取外边的。
import com.lowagie.text.pdf.BaseFont;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.*;
import java.util.List;
import java.util.Map;
/**
* @author lxz
* pdf导出
*/
@Slf4j
public class PdfExportUtil {
/**
*
* @param list 需要写入 PDF 的字符串集合
* @param fileName 生成的 PDF 文件名
* @throws IOException 如果发生 IO 异常
*/
public static String exportPdf(List<Map<String,String>> list, String fileName) throws IOException {
// 创建临时文件
String path = System.getProperty("user.dir") + File.separator + fileName + ".pdf";
log.info("【pdf生成】,路径:" + path);
File tempFile = new File(path);
if (!tempFile.exists()) {
log.info("【pdf生成】,文件不存在创建!");
tempFile.createNewFile();
}
// 使用 FileOutputStream 将 PDF 写入到临时文件
log.info("【pdf生成】,完成html内容生成!");
// 生成html内容
String htmlContent = generateHtmlContent(list, fileName);
// 创建ITextRenderer实例
ITextRenderer renderer = new ITextRenderer();
// 设置字体路径,从 resources/fonts 目录加载 SimSun 字体
ITextFontResolver fontResolver = renderer.getFontResolver();
Resource resource = new ClassPathResource("fonts/SimSun.ttf");
File newFontDir = new File(System.getProperty("user.dir") + File.separator + "fonts");
if (!newFontDir.exists()) {
newFontDir.mkdirs();
}
File newFontFile = new File(newFontDir, "SimSun.ttf");
if (!newFontFile.exists()) {
newFontFile.createNewFile();
// 将 resource 内容写入 newFontFile
try (InputStream inputStream = resource.getInputStream();
OutputStream outputStream = new FileOutputStream(newFontFile)) {
// 使用缓冲区进行复制
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
log.info("【pdf下载】,字体文件已成功复制到" + newFontFile.getAbsolutePath());
} else {
log.info("【pdf下载】,字体已存在:" + newFontFile.getAbsolutePath());
}
fontResolver.addFont(newFontFile.getPath(), BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
log.info("【pdf生成】,加载字体成功!");
// 设置HTML内容
renderer.setDocumentFromString(htmlContent);
log.info("【pdf生成】,生成内容!");
renderer.layout();
// 输出PDF到响应输出流
try (OutputStream outputStream = new FileOutputStream(tempFile)) {
renderer.createPDF(outputStream);
outputStream.flush();
log.info("【pdf生成】,生成完成!");
} catch (Exception e) {
e.printStackTrace();
}
return path;
}
/**
* 生成HTML内容
* @return 渲染后的HTML字符串
*/
public static String generateHtmlContent(List<Map<String,String>> list, String fileName) {
//thymeleaf构造模板引擎;给html文件赋值
ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
//默认是找classpath路径下的资源
resolver.setPrefix("templates/");
//模板文件后缀
resolver.setSuffix(".html");
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(resolver);
log.info("【pdf生成】,填充html内容!");
Context context = new Context();
context.setVariable("title", fileName);
context.setVariable("list", list);
return templateEngine.process("pdf_template", context);
}
}
字体文件:
3.模板文件
resource/templates目录下。
主要靠thymeleaf来实现的。
内容如下:
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<title th:text="${title}"></title>
<style>
body {
font-family: 'SimSun', sans-serif;
}
</style>
</head>
<body>
<div data-th-each="item:${list}">
<div th:text="${item.content}" th:style="${item.style}"></div>
</div>
</body>
</html>
4.测试方法
@RestController
@RequestMapping("/api/pdf")
public class PdfController {
@GetMapping("/test")
@TinyResponse
public void downloadPdf() throws Exception {
List<Map<String,String>> list = new ArrayList<>();
for (int i =0; i< 100; i++) {
Map<String,String> map = new HashMap<>();
map.put("content", "测试内容生成111111");
map.put("style", "color:red;font-size: 12px;");
list.add(map);
}
String fileName = "测试pdf名称";
PdfExportUtil.exportPdf(list, fileName);
}
}