当前位置: 首页 > news >正文

Java中实现html转pdf

背景

最近项目中需要生成日报文件,日报文件的格式为pdf,且日报的样式相对而言比较复杂,存在多段文字,存在多个表格,且存在样式。目前想到的解决办法是
先生成html文件,让后将html文件转换成pdf文件。通过网上搜索,发现openhtmltopdf可以实现我们的需求,此处记录一下。

2、需求

  1. 生成的pdf需要支持中文。
  2. 生成的pdf支持简单的样式。(此处可以使用css样式来解决,但不是所有的css样式都支持)
  3. 生成的pdf存在表格,每行应完整地出现在同一页,不要一半在上一页、一半在下一页。
  4. 生成的pdf可以自己指定到分页,比如某个表格的数据渲染完之后,需要单独开启一页。
  5. 生成的pdf支持密码加密。
  6. 生成的pdf可以支持纸张规格,比如是A3还是A4,并且还可设置横向还是纵向。

3、思路

1、html的生成,我们可以通过freemarker来实现。
2、html转pdf,通过openhtmltopdf来实现。

4、实现步骤

4.1 搭建一个简单的工程

首先搭建一个简单的可运行的程序,可实现Freemarker渲染模板,然后生成pdf文件

4.1.1 引入依赖

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.0</version>
</dependency>
<!-- 模板引擎,用于渲染html -->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.30</version>
</dependency>
<!-- 用于将html转换成pdf -->
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-pdfbox</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
</dependency>
</dependencies>

4.1.2 编写Freemarker工具类

加载程序中src/main/resources/templates/ftls目录下的模板文件,然后渲染成html内容。

package com.huan.pdf.utils;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import java.io.StringWriter;
import java.util.Map;
/**
* freemarker 工具类
*
* @author admin
*/
@Slf4j
public class FreemarkerUtils {
/**
* 模板文件夹路径
*/
private static final String TEMPLATE_DIR = "/templates/ftls";
private static final Configuration CONFIGURATION;
static {
CONFIGURATION = new Configuration(Configuration.VERSION_2_3_30);
CONFIGURATION.setTemplateLoader(new ClassTemplateLoader(FreemarkerUtils.class, TEMPLATE_DIR));
CONFIGURATION.setDefaultEncoding("UTF-8");
CONFIGURATION.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
CONFIGURATION.setLogTemplateExceptions(false);
CONFIGURATION.setWrapUncheckedExceptions(true);
}
/**
* 根据模板名称和数据模型生成字符串
*
* @param templateName 模板名称
* @param dataModel 数据模型
* @return 生成的字符串
*/
public static String processTemplate(String templateName, Map<String, Object> dataModel) {
try {
Template template = CONFIGURATION.getTemplate(templateName);
StringWriter writer = new StringWriter();
template.process(dataModel, writer);
return writer.toString();
} catch (Exception e) {
log.error("解析模板出现问题", e);
}
return "";
}
}

4.1.3 编写pdf工具类

编写pdf工具类,用于将html内容渲染成pdf文件,此处只是简单实现,后期该类还需要修改

package com.huan.pdf.utils;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
/**
* pdf工具类
*
* @author admin
*/
@Slf4j
public class PdfUtils {
/**
* 生成pdf文件
*
* @param pdfTemplate pdf模板
* @param response http response
*/
public static void generatePdf(String pdfTemplate, HttpServletResponse response) {
// 设置响应头
String fileName = UUID.randomUUID() + ".pdf";
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
try (OutputStream os = response.getOutputStream()) {
PdfRendererBuilder builder = new PdfRendererBuilder();
builder.withHtmlContent(pdfTemplate, null);
builder.toStream(os);
builder.run();
} catch (IOException e) {
log.error("生成pdf文件失败", e);
throw new RuntimeException("生成pdf文件失败", e);
}
}
}

4.1.4 增加一个模板

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>生成pdf</title>
<style>
.main-title { text-align: center; font-size:25px; }
</style>
</head>
<body>
<div class="main-title">${mainTitle}</div>
</body>
</html>

该模板中存在变量mainTitle,这个变量的值通过后台来赋值

4.1.5 增加一个控制层

package com.huan.pdf.controller;
import com.huan.pdf.utils.FreemarkerUtils;
import com.huan.pdf.utils.PdfUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
/**
* pdf控制器
*
* @author admin
*/
@RestController
public class PdfController {
@GetMapping("pdf")
public void pdf(HttpServletResponse response) {
Map<String, Object> params = new HashMap<>(16);
params.put("mainTitle", "这是一个标题 - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
// 渲染模板
String htmlContent = FreemarkerUtils.processTemplate("pdf.ftl", params);
// 生成pdf
PdfUtils.generatePdf(htmlContent, response);
}
}
http://www.gsyq.cn/news/1611421.html

相关文章:

  • 2026年值得关注的AI外呼厂商盘点:从云厂商到垂直方案,怎么选更合适?
  • 3-IPV6域名解析
  • 实战掌握Adobe软件激活:全面解析GenP 3.0破解工具高效配置
  • 后端性能瓶颈排查实战:从慢接口到系统优化的完整落地思路
  • 大部分人都在管别人的闲事
  • 而 C++ 就是这种能自举的编程语言
  • 【Claude】Claude Code 代码审查实战指南:一次对话审出 26 个 Bug 的方法论
  • Go模块管理教程
  • 【最新测评】有没有降AI率的靠谱网站推荐?2026年实测15款降AI神器,省钱又高效!
  • CSDN自动化测试_草稿
  • 临沂GEO技术应用与合规解析
  • Docker部署项目实践
  • Docker Compose详解
  • Go协程Goroutine原理
  • C++智能指针开发实践
  • Java锁机制深入分析
  • 文件的权限属性
  • Python列表与元组深度解析
  • M4Markets:合规意识的路径评估
  • 如何通过5个核心技术模块让《环世界》性能提升400%?Performance-Fish深度架构解析
  • React状态管理指南
  • open harmony 项目实战:学习打卡功能如何设计更有激励感
  • Python异常处理完整教程
  • Java垃圾回收机制详解
  • Nginx反向代理教程
  • C++类与对象开发实践
  • React性能优化技巧
  • 别再只盯着内核了!手把手教你用BusyBox为嵌入式Linux打造最小根文件系统
  • MoE稀疏激活原理与工程实践:解密大模型2%参数激活真相
  • Rust语言快速入门