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

后端 PDF 生成方案(OpenPDF + Thymeleaf)

前言

        企业项目中可能存在需要生成一些 PDF 报表的功能,需要后端提供一个下载 PDF 的接口,本文将介绍通过采用 OpenPDF + Thymeleaf 的技术方案来解决该问题。


什么是 OpenPDF

        他是基于 iText 的开源替代方案,通过使用 OpenPDF 可以让我们生成 PDF 文件。相较于 iText,OpenPDF 更加轻量级,API 设计更加简洁。它允许商业使用,无传染性,适合企业项目。

核心功能

  • 基础 PDF 生成(文本、表格、图片)

  • 简单表单填充与加密(AES-128)

  • HTML 转 PDF(需配合 Flying Saucer)


什么是 Thymeleaf

        用于 Java 应用中动态生成 HTML、XML 等文件的工具。

        与 Spring 深度集成,可以在 Spring 项目直接进行引入。


Demo 实践

业务场景

        项目中存在报表导出功能,前端为我们传入数据,需要后端对于数据进行整理然后生成对应的 PDF 文件报表进行返回。需要注意的是,我们的 PDF 文件中可能存在中文和图片,需要支持中文和图片的渲染。

实现流程

1、引入 Maven 依赖

<!--    Web开发启动项    -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--    单元测试    -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--    模板引擎(动态生成HTML文件)    -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--    替代 iText 的开源 PDF 操作库,用于生成 PDF 文件    -->
<dependency>
    <groupId>com.github.librepdf</groupId>
    <artifactId>openpdf</artifactId>
    <version>1.3.38</version>
</dependency>
<!--    基于 OpenPDF 的 HTML/CSS 渲染引擎,将模板渲染为 PDF    -->
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>flying-saucer-pdf-openpdf</artifactId>
    <version>9.1.22</version>
</dependency>

2、准备静态资源文件

  • src/main/resources/templates/index.html:用于测试请求。

  • src/main/resources/templates/pdf-template.html:生成的 PDF 模板文件(通过 Thymeleaf)动态渲染。

  • src/main/resources/static/images/1111.png:用作测试的图片。

  • src/main/resources/static/fonts/simhei.ttf:支持中文的字体。

3、编写 Controller

@Controller
public class PdfController {
    @Autowired
    private PdfGenerationService pdfService;
    @GetMapping("/")
    public String index() {
        return "index";
    }
    @PostMapping("/generate-pdf")
    public void generatePdf(@RequestParam String name,
                            HttpServletRequest request,
                            HttpServletResponse response) throws IOException {
        String userAgent = request.getHeader("User-Agent");
        pdfService.generatePdf(response, name, userAgent);
    }
}

4、编写 Service

@Service
public class PdfGenerationService {

    //自动注入Thymeleaf模板引擎,用于处理HTML模板
    @Autowired
    private TemplateEngine templateEngine;

    public void generatePdf(HttpServletResponse response, String name, String userAgent) throws IOException {
        Context ctx = new Context();
        ctx.setVariable("name", name);
        ctx.setVariable("timestamp", new Date());
        ctx.setVariable("userAgent", userAgent);

        try {
            String processedHtml = templateEngine.process("pdf-template", ctx);
            //设置响应头信息
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition", "attachment; filename=\"generated-pdf.pdf\"");

            //创建PDF渲染器
            ITextRenderer renderer = new ITextRenderer();

            //添加字体解析
            configureChineseFont(renderer);

            // 添加图片路径解析
            ClassPathResource imgResource = new ClassPathResource("static/images/");
            String baseUrl = imgResource.getURL().toString();
            renderer.getSharedContext().setBaseURL(baseUrl);

            //将HTML转化为PDF
            renderer.setDocumentFromString(processedHtml);
            renderer.layout();
            renderer.createPDF(response.getOutputStream());
            renderer.finishPDF();
            
        } catch (DocumentException e) {
            throw new IOException("Error generating PDF", e);
        }
    }

    /**
     * 注册字体文件
     * @param renderer
     * @throws DocumentException
     * @throws IOException
     */
    private void configureChineseFont(ITextRenderer renderer) throws DocumentException, IOException {
        try {
            ClassPathResource fontResource = new ClassPathResource("static/fonts/simhei.ttf");
            String fontPath = fontResource.getURL().toString();
            renderer.getFontResolver().addFont(
                    fontPath,
                    BaseFont.IDENTITY_H,
                    BaseFont.NOT_EMBEDDED
            );
        } catch (Exception e) {
            throw new DocumentException("字体加载失败: " + e.getMessage());
        }
    }
}

测试

  1. 进入 index 页面。

  1. 填写 name,后点击 Generate PDF 创建对应 PDF。

  2. 查看下载的 PDF,如下:

        至此,需求满足,后续根据需求添加需求项即可。


总结

        总结了企业中实现后端生成 PDF 的解决方案。通过使用 OpenPDF + Thymeleaf 的方案,该方案学习成本低,且无商业问题,适用于较低性能需求下的 PDF 生成问题。

Demo 代码 GitHub 源地址:https://github.com/Djhhhhhh/MakePDFdemo


http://www.kler.cn/a/571032.html

相关文章:

  • DApp开发中的模式设计、功能文档与代币对接解析
  • 【深度学习】—— Keras快速入门
  • rust学习笔记7-344. 反转字符串
  • 大疆机场3发布:车载移动部署新突破,无人机技术再升级
  • FPGA开发,使用Deepseek V3还是R1(6):以滤波器为例
  • OpenHarmony启动恢复子系统
  • 机器学习的起点:线性回归Linear Regression
  • Linux知识-第一天
  • 【音视频】H265解码Nalu后封装rtp包
  • AI应用开发 3 - prompt 提示词工程
  • Grafana服务安装并启动
  • 一文快速掌握前端框架Nextjs
  • csrf与ssrf学习笔记
  • 计算机基础面试(数据结构)
  • 【量化策略】双均线交叉策略
  • Oracle+11g+笔记(10)-数据库控制
  • 探秘基带算法:从原理到5G时代的通信变革【七】FFT/DFT
  • GitHub开源协议选择指南:如何为你的项目找到最佳“许可证”?
  • 基于开源库编写MQTT通讯
  • 计算机毕业设计SpringBoot+Vue.js纺织品企业财务管理系统(源码+文档+PPT+讲解)