完美!SpringBoot + HTML模板高效生成PDF文档

开发 前端
OpenHtmlToPdf 是一个功能强大的开源Java库,专为将HTML内容转换为高质量的PDF文档而设计。它以其出色的HTML和CSS兼容性、灵活的配置选项以及易于集成的特点而广泛的认可和应用。​

环境:SpringBoot3.2.8

1. 简介

OpenHtmlToPdf是一个开源的Java库,专为将HTML内容转换为PDF文档而设计。它支持大部分CSS样式和部分HTML5特性,使得从网页或HTML模板生成高质量的PDF文件变得简单高效。OpenHtmlToPdf不仅提供了基础的HTML到PDF的转换功能,还允许用户通过丰富的配置选项来自定义PDF文档的样式和输出设置。该组件的引入,极大地简化了项目中生成PDF文档的工作流程,无论是用于生成报告、合同、还是电子书等场景,都能轻松应对。

接下来我们将在SpringBoot项目中,通过Freemarker模板引擎渲染HTML模板,并利用OpenHtmlToPdf库将渲染后的HTML内容转换为PDF文档,最后通过HTTP响应将PDF文件提供给用户下载。

2. 实战案例

2.1 引入依赖

<!-- 该库进行HTML的解析 -->
<dependency>    
  <groupId>org.jsoup</groupId>    
  <artifactId>jsoup</artifactId>   
  <version>1.18.1</version> 
</dependency>
<!-- 将HTML内容转换为PDF文档 -->
<dependency>
  <groupId>com.openhtmltopdf</groupId>
  <artifactId>openhtmltopdf-core</artifactId>
  <version>${openhtmltopdf.version}</version>
</dependency>
<dependency>
  <groupId>com.openhtmltopdf</groupId>
  <artifactId>openhtmltopdf-pdfbox</artifactId>
  <version>${openhtmltopdf.version}</version>
</dependency>

接下来是准备需要的资源

2.2 资源准备

要支持中文,需要进行字体的准备,我这里使用的BabelStoneHan.ttf

图片图片

我们要通过freemarker模板技术生成HTML文档,还需要准备ftl模板,内容如下:

<html>
 <head>
  <meta charset="UTF-8">
  <title>用户列表</title>
  <style>
    body {font-family: "BabelStoneHan",sans-serif;}
    table {width: 100%;border-collapse: collapse;}
    th,td {border: 1px solid black;padding: 8px;text-align: left;}  
    th {background-color: #f2f2f2;}  
</style>
 </head>
 <body>
  <div class="title-container">
    <h2>XXXOOO全部用户列表信息</h2>
  </div>
  <div class="content-container">
    <table>  
      <tr>  
        <th>编号</th>  
        <th>姓名</th>  
        <th>性别</th>  
        <th>身份证</th>  
        <th>年龄</th>  
        <th>邮箱</th>  
        <th>头像</th>  
      </tr> 
      <#list users as user>
        <tr>  
          <td>${user.id}</td>  
          <td>${user.name}</td>  
          <td>${user.sex}</td>  
          <td>${user.idNo}</td>  
          <td>${user.age}</td>  
          <td>${user.email}</td>  
          <td><img src="https://img0.baidu.com/it/u=3366443890,3137275928&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" alt="Avatar" style="width:50px;"></td>
        </tr>
      </#list>
    </table> 
  </div>
 </body>
</html>

模板保存路径如下

图片图片

基础资源都准备好后,接下来就是进入代码编写了

2.3 基础配置&准备数据

对freemarker进行基本的配置,如:编码,模板路径等。

@Bean
Configuration config(ResourceLoader loader) {
  freemarker.template.Configuration cfg = null ;
  try {
    cfg = new Configuration(Configuration.VERSION_2_3_33);
    // 设置模板路径
    File baseDir = loader.getResource("classpath:/templates/").getFile() ; 
    TemplateLoader templateLoader = new FileTemplateLoader(baseDir) ;
    cfg.setTemplateLoader(templateLoader) ;
    // 设置编码
    cfg.setDefaultEncoding("UTF-8") ;
    cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER)  ;
  } catch (IOException e) {
    e.printStackTrace() ;
  }
  return cfg ;
}

以后要具体使用模板都会通过这里的Configuration获取。

准备数据,这里为了足够的简单,并不去DB查询数据。

private static final List<User> DATAS = new ArrayList<>() ;
static {
  for (int i = 0; i < 10; i++) {
    DATAS.add(new User(
        i + 0L, 
        "姓名 - " + i, 
        new Random().nextInt(3) % 2 == 0 ? "男" : "女", 
        "身份证 - " + i, 
        new Random().nextInt(100), 
        i + "@qq.com", 
        "avatar.png") // 头像实际在模板中写死了
      ) ;
  }
}

以上工作做完后接下来就可以进行PDF的生成了。我这里会直接通过一个Controller接口生成&下载PDF文档。

2.4 生成PDF

@RestController
@RequestMapping("/users")
public class UserController {
  private final Configuration cfg ;
  public UserController(Configuration cfg) {
    this.cfg = cfg ;
  }
  
  // 生成PDF
  @GetMapping("/gen")
  public Object gen(HttpServletResponse response) {
    // 设置文件下载Header
    String fileName = new String("用户列表.pdf".getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1) ;
    response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
    response.setContentType("application/octet-stream") ;
    try {
      // 获取模板
      Template template = this.cfg.getTemplate("users.ftl") ;
      // 准备模板需要的数据
      Map<String, Object> root = new HashMap<>() ;
      root.put("users", DATAS) ;
      // 生成HTML内容到内存中
      ByteArrayOutputStream baos = new ByteArrayOutputStream() ;
      Writer out = new OutputStreamWriter(baos) ;
      template.process(root, out) ;
      
      // 将上面生成的HTML内容进行解析
      Document document = Jsoup.parse(baos.toString(StandardCharsets.UTF_8), "UTF-8") ;
      // 设置HTML语法
      document.outputSettings().syntax(Document.OutputSettings.Syntax.html) ;
      // 构建PDF文档,最后将上面的Document进行输出
      PdfRendererBuilder builder = new PdfRendererBuilder();
      // 使用字体,字体名要与模板中CSS样式中指定的字体名相同
      builder.useFont(new ClassPathResource("/fonts/BabelStoneHan.ttf").getFile(), "BabelStoneHan", 1, BaseRendererBuilder.FontStyle.NORMAL, true);
      builder.toStream(response.getOutputStream()) ;
      builder.useFastMode() ;
      builder.withW3cDocument(new W3CDom().fromJsoup(document), new ClassPathResource("/templates/").getPath());
      builder.run() ;
    } catch (Exception e) {
      e.printStackTrace() ;
    }
    return "生成成功" ;
  }
}

测试访问/users/gen接口。

图片图片

PDF文档正常生成了。

总结:OpenHtmlToPdf 是一个功能强大的开源Java库,专为将HTML内容转换为高质量的PDF文档而设计。它以其出色的HTML和CSS兼容性、灵活的配置选项以及易于集成的特点而广泛的认可和应用。

责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2024-08-30 11:28:09

2024-09-30 08:10:22

2023-02-26 10:16:19

JavaPDF文档

2024-09-03 08:26:59

Spring格式模板

2022-11-23 07:30:11

2023-12-12 13:42:00

微服务生态系统Spring

2024-08-13 10:36:25

SpringScrew数据库

2023-12-29 09:04:01

前端文件处理库PDF.js

2021-09-15 07:33:33

Java开发在线

2009-08-24 18:00:52

ASP.NET模板生成

2010-08-25 08:58:32

HTML

2012-07-19 09:38:04

Office 2013

2023-07-04 08:38:22

AIDevOps软件

2020-10-09 09:40:59

GNOME桌面主题桌面应用

2009-11-25 09:57:17

PHPPDF

2023-07-06 22:29:22

pdftkPDF书签

2021-03-18 07:33:54

PDF DinkToPdfC++

2013-08-20 17:05:38

HTML5 BoileWeb App模块化

2023-04-14 19:19:09

CSSHTML文档

2023-11-10 09:16:45

SpringBootThymeleaf
点赞
收藏

51CTO技术栈公众号