Thymeleaf enterprise-level real application: convert HTML interface data to PDF output

Table of contents

1. Thymeleaf Description

1.1 What is Thymeleaf

1.2 Thymeleaf has characteristics

 2. Convert HTML interface data to PDF output logic description

2.1 Central idea

2.2 Operating Instructions 

2.3 Specific steps

3. Specific implementation 

 3.1 Add dependencies

 3.2 Define HTML template

 3.3 HTML template rendering tool

 3.4 Read the rendering result of the html template and convert it to a Base64 string

 3.4.1 Library: ITextRenderer Description

 3.4.2 Class: Description of ITextFontResolver

3.4.3 Conversion to Base64 summary instructions

 3.5 After converting base64 to PDF, return the path of the current pdf

3.5.1 Description of ByteArrayOutputStream

3.6 Method integration and use


 

 The use of Thymeleaf template engine, another artifact of Java

1. Thymeleaf Description

1.1 What is Thymeleaf

Thymeleaf is a modern server-side Java templating engine that can be used for HTML, XML, JavaScript, CSS, and text on the web and in standalone environments . In actual development, Thymeleaf can be used to generate dynamic HTML pages, support binding data with templates , and generate final HTML content. It is an open source software released under the Apache License 2.0.

1.2 Thymeleaf has characteristics

Compared with other server-side Java template engines, Thymeleaf has the following characteristics:

  • The syntax is simple and easy to understand, and supports natural HTML tags
  • Supports HTML5 specifications and features
  • Support binding and manipulation of CSS styles
  • Support Expression Language (EL for short) and Spring Expression Language (SpEL for short)
  • Support multiple template rendering methods of standard and Spring MVC
  • Supports multiple template caching strategies
  • Supports scalable engine architecture

In actual development, Thymeleaf can be used to generate dynamic HTML pages, support binding data with templates, and generate final HTML content. It can be used as a templating engine for web applications, or as a templating engine for other applications. Due to its easy-to-use syntax and powerful functions, Thymeleaf has become one of the most popular template engines in the Java field.

 2. Convert HTML interface data to PDF output logic description

2.1 Central idea

Template files and data models using template engines . The template file defines the structure and style of the final output PDF page, while the data model provides the dynamic data to be populated in the template.

Specifically, Thymeleaf uses Java objects as a data model, and data can be injected into the data model through Spring's controllers. Thymeleaf then combines the data model with the template files to generate HTML content . Finally, use a PDF generation library to convert the HTML content to PDF output.

2.2 Operating Instructions 

When implementing the PDF output function, you can use spring-boot-starter-thymeleafthe dependencies provided by Spring Boot, which include Thymeleaf, PDF generation library and other required dependencies. Thymeleaf objects can be used in the controller TemplateEngineto combine data models and template files to generate HTML content. The HTML content can then be converted to PDF format using a PDF generation library.

It should be noted that PDF output may require some specific CSS styles and HTML markup in order to render and format PDF pages properly. Therefore, before generating PDF output, the template file may need to be adjusted and optimized to ensure that the output PDF pages have the desired appearance and layout.

2.3 Specific steps

  1. Define an HTML template, create a template in HTML format for the data that needs to be output, and generate a .HTML file
  2. Introduce TemplateEngine-"Java template engine framework for generating text output in Thymeleaf, Context-》context object of Web application. Generate html template rendering tool. Process the template we defined above. Get a String result
  3. Read the result byte[] and convert the byte array to a Base64 string
  4. Finally, convert the Base64 string to data in PDF format, the output path
     

3. Specific implementation 

 3.1 Add dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

 3.2 Define HTML template

<html>
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1>Hello, ${name}!</h1>
        <p>You are ${age} years old.</p>
    </body>
</html>

 3.3 HTML template rendering tool

import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import java.util.Map;


/**
 * html 模板渲染工具
 */
@Component
public class HtmlTemplate {
    @Resource
    private TemplateEngine templateEngine;

    /**
     * 使用 Thymeleaf 渲染 HTML
     * @param template HTML模板
     * @param params 参数
     * @return
     * @throws Exception
     */
    public String render(String template, Map<String,Object> params) throws Exception {
        // 创建模板上下文
        Context context = new Context();
        // 设置变量
        context.setVariables(params);
        //将数据填充到模板里,开始处理模板
        return templateEngine.process(template, context);
    }

}

 3.4 Read the rendering result of the html template and convert it to a Base64 string

font path 

 PdfUtils 

import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.ByteArrayOutputStream;

public class PdfUtils {
   
    public static String getPdfBase64ByHtml(String html) throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//构建字节输出流
        ITextRenderer renderer = new ITextRenderer();
        ITextFontResolver fontResolver = renderer.getFontResolver();
        //指定文件字体添加到PDF库,指定字体不作为内部字体,而是外部字体被加载
        fontResolver.addFont("pdf/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        renderer.setDocumentFromString(html);
        renderer.layout();
        renderer.createPDF(baos);
        return Base64Utils.encode(baos.toByteArray());
    }
}

After adding the font file, you can use setDocumentFromString()the method to set the HTML document into the renderer, and use layout()the method to layout the document. Next, use createPDF()the method to render the document to PDF and output it to the output stream.

Note that when adding a font file, you need to ensure that the path of the font file is correct and that the font file can be read. In addition, you also need to ensure that the format of the font file is correct, you can use BaseFont.IDENTITY_Hthe specified font encoding, and use BaseFont.NOT_EMBEDDEDthe specified font file to embed it into the PDF file.

 Base64Utils


import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import java.io.*;

/**
 * Base64 转换工具
 */
public class Base64Utils {

    /**
     * byte数组 转换为 Base64字符串
     */
    public static String encode(byte[] data) {
        return new BASE64Encoder().encode(data);
    }

    /**
     * Base64字符串 转换为 byte数组
     */
    public static byte[] decode(String base64) {
        try {
            return new BASE64Decoder().decodeBuffer(base64);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new byte[0];
    }

    /**
     * 把文件内容编码为 Base64字符串, 只能编码小文件(例如文本、图片等)
     */
    public static String encodeFile(File file) throws Exception {
        InputStream in = null;
        ByteArrayOutputStream bytesOut = null;

        try {
            in = new FileInputStream(file);
            bytesOut = new ByteArrayOutputStream((int) file.length());

            byte[] buf = new byte[1024];
            int len = -1;

            while ((len = in.read(buf)) != -1) {
                bytesOut.write(buf, 0, len);
            }
            bytesOut.flush();

            return encode(bytesOut.toByteArray());

        } finally {
            close(in);
            close(bytesOut);
        }
    }

    /**
     * 把 Base64字符串 转换为 byte数组, 保存到指定文件
     */
    public static void decodeFile(String base64, File file) throws Exception {
        OutputStream fileOut = null;
        try {
            fileOut = new FileOutputStream(file);
            fileOut.write(decode(base64));
            fileOut.flush();
        } finally {
            close(fileOut);
        }
    }

    private static void close(Closeable c) {
        if (c != null) {
            try {
                c.close();
            } catch (IOException e) {
                // nothing
            }
        }
    }

}

 3.4.1 Library: ITextRenderer Description

ITextRenderer is a Java library based on the iText library, which can render documents such as HTML, XHTML or XML into PDF, XLS, PNG, JPEG and other formats.

The ITextRenderer library provides a ITextRendererclass that provides a rich API for converting HTML, XHTML, or XML documents into files in formats such as PDF. This class internally uses the PDF generation and manipulation functions of the iText library, and also supports the rendering and layout of documents using the Flying Saucer library.

The basic process of using the ITextRenderer library for PDF output is as follows:

  1. create an ITextRendererobject;
  2. setDocument()Set the document to be converted into the renderer using the method;
  3. layout()Typesetting and layout of documents using methods;
  4. Use createPDF()method to render document to PDF, and output to output stream or file.

 3.4.2 Class: Description of ITextFontResolver

ITextFontResolver is a class in the ITextRenderer library, which is used to manage and parse font files and provide font support for PDF generation.

In the ITextRenderer library, when using HTML documents to generate PDF, since PDF does not support all fonts used in HTML, it is necessary to replace the fonts in HTML with fonts supported by PDF before generating PDF. ITextFontResolver provides a addFont()method, which is used to add font files to ITextFontResolver for management, so as to be used when PDF is generated.

DEMO description:

// 创建一个ITextRenderer对象
ITextRenderer renderer = new ITextRenderer();

// 创建一个ITextFontResolver对象
ITextFontResolver fontResolver = renderer.getFontResolver();

// 添加字体文件
fontResolver.addFont("pdf/font/simsun.ttc", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);

First, an object is created ITextRenderer, then the object getFontResolver()is obtained through the method ITextFontResolver, and the font file to be used is added to ITextFontResolverthe object.

3.4.3 Conversion to Base64 summary instructions

Base64 is an encoding method used to convert binary data into text data. Binary data such as pictures, audio, and video can be converted into text data through Base64 encoding, so as to facilitate transmission on the network.

 3.5 After converting base64 to PDF, return the path of the current pdf

public class Base64Util {

    public static String base64StringToPDF(String base64, String path) {


        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String fileAdd = sdf.format(new Date());
        //先判断文件是否存在
        path = path + "/" + fileAdd;
        String fileName = path + "/" + System.currentTimeMillis() + ".pdf";//新的文件名

        BufferedInputStream bin = null;
        FileOutputStream fout = null;
        BufferedOutputStream bout = null;
        BASE64Decoder decoder = new BASE64Decoder();
        try {
            byte[] bytes = decoder.decodeBuffer(base64);

            ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
            // 创建从底层输入流中读取数据的缓冲输入流对象
            bin = new BufferedInputStream(bais);

            //获取文件夹路径
            File file = new File(path);
            //如果文件夹不存在则创建
            if (!file.exists() && !file.isDirectory()) {
                file.mkdirs();
            }
            // 创建到指定文件的输出流
            fout = new FileOutputStream(fileName);
            // 为文件输出流对接缓冲输出流对象
            bout = new BufferedOutputStream(fout);
            byte[] buffers = new byte[1024];
            int len = bin.read(buffers);
            while (len != -1) {
                bout.write(buffers, 0, len);
                len = bin.read(buffers);
            }
            // 刷新此输出流并强制写出所有缓冲的输出字节,必须这行代码,否则有可能有问题
            bout.flush();
            //返回存储的路径
            return fileName;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bin.close();
                fout.close();
                bout.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }
}

3.5.1 Description of ByteArrayOutputStream

ByteArrayOutputStreamIs a class in the Java IO library that provides a buffer that can write data to a byte array in memory . When data is written into the cache, if the size of the cache is insufficient,the size of the cacheByteArrayOutputStreamwill beto accommodate more data.

ByteArrayOutputStreamThe main function of is to create a variable-length byte array in memory, write data into the byte array, and then toByteArray()get the complete byte array by calling the method . Typically, ByteArrayOutputStreamit is used to cache intermediate results for use in subsequent operations.

3.6 Method integration and use

@Autowired
private HtmlTemplate htmlTemplate;


@Override
public String changeTaskReport() throws Exception {
        Map<String, Object> map = new HashMap();
        StringBuffer sb = new StringBuffer();

        data.put("name", "Alice");
        data.put("age", 20);

        String html = htmlTemplate.render("Template.html", map);
        String base64 = PdfUtils.getPdfBase64ByHtml(html);
        String pdfAdd = Base64Util.base64StringToPDF(base64, fileConfig.getPdfAdd());
        return pdfAdd;
}

Slow is fast, time is not data for development, it is philosophy

Guess you like

Origin blog.csdn.net/qq_45656077/article/details/129954204