Skip to content

Spring Boot Convert Html to Pdf By Freemarker Template

Overview

之前有一个需求,需要生成 pdf 报告文件,采用 html 转 pdf 可以很好的保证样式,本文记录下采用 freemarker 动态模板生成 html,然后转成 pdf 的方式

Maven Dependencies

在 pom.xml 文件中添加以下依赖

xml
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
          <!-- Flying Saucer dependencies for HTML to PDF conversion -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-core</artifactId>
            <version>9.1.22</version>
        </dependency>
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-openpdf</artifactId>
            <version>9.1.22</version>
        </dependency>

    </dependencies>

Define Freemarker Template

在 resources 下面新建目录 templates, 然后创建 template.ftl 文件

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>PDF Example</title>
    <style>
      h1 {
        text-align: center;
        color: cadetblue;
      }
    </style>
  </head>
  <body>
    <h1>${title}</h1>
    <p>${content}</p>
  </body>
</html>

Define Service

创建一个服务类,用于渲染 Freemarker 模板并将 HTML 转换为 PDF:

java
public interface PdfGenerator {

    byte[] generator(String templateName, Map<String,Object> data) throws Exception;
}
java
@Service
public class FreeMarkerPdf implements PdfGenerator{

    private final Configuration freemarkerConfig;

    public FreeMarkerPdf(Configuration freemarkerConfig) {
        this.freemarkerConfig = freemarkerConfig;
    }

    @Override
    public byte[] generator(String templateName, Map<String, Object> data) throws Exception {
        Template template = freemarkerConfig.getTemplate("template.ftl","UTF-8");
        String html =  FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()){
            ITextRenderer renderer = new ITextRenderer();
            renderer.setDocumentFromString(html);
            renderer.layout();
            renderer.createPDF(outputStream);
            return outputStream.toByteArray();
        }
    }
}

Define Controller

创建一个控制器,用于处理生成 PDF 的请求的测试接口:

java
@RequestMapping("pdf")
@RestController
public class TestController {

    private final PdfGenerator pdfGenerator;

    public TestController(PdfGenerator pdfGenerator) {
        this.pdfGenerator = pdfGenerator;
    }

    @GetMapping
    public void pdf(HttpServletResponse response,@RequestParam String title,@RequestParam String content) throws Exception {
        Map<String, Object> data = new HashMap<>();
        data.put("title", title);
        data.put("content", content);
        byte[] bytes = pdfGenerator.generator("template,ftl", data);
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=generated.pdf");
        response.setContentLength(bytes.length);
        try (OutputStream os = response.getOutputStream()) {
            os.write(bytes);
        }
    }
}

Test

浏览中输入 http://127.0.0.1:8080/pdf?title=test&content=hello 可以看到可以下载 pdf 文件,打开 pdf 文件,可以看到以下内容 project

Released under the MIT License.