springboot 使用itextpdf、thymeleaf,将html转为PDF

itextpdf目前使用的是5版本的

1.导入基础包

<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
  <groupId>com.itextpdf</groupId>
  <artifactId>itextpdf</artifactId>
  <version>5.5.11</version>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf.tool/xmlworker -->
<dependency>
  <groupId>com.itextpdf.tool</groupId>
  <artifactId>xmlworker</artifactId>
  <version>5.5.11</version>
</dependency>
        <!--css高级样式支持-->
        <!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf</artifactId>
            <version>9.1.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.xhtmlrenderer/flying-saucer-pdf-itext5 -->
        <dependency>
            <groupId>org.xhtmlrenderer</groupId>
            <artifactId>flying-saucer-pdf-itext5</artifactId>
            <version>9.1.5</version>
        </dependency>

2.创建HTML模板

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>2</title>
    <style>
        /*这是将打印时的页面大小设置为A4大小,并保留好一定的边距 210×297mm*/
        @page {
            size: 21cm 29.7cm;
            font-size: 14pt;
            color: black;
            line-height: 1.4;
            text-align: justify;
            margin: 0;
            padding: 0;
        }
        body {
            font-family: FZLanTingHei-L-GBK;
            width: 21cm;
            height: 29.7cm;
            margin: 0;
            padding: 0;
            overflow: hidden;
        }
        img{
            width: 21cm;
            height: 29.7cm;
        }
    </style>
</head>
<body>
<div align="center">
    <img src="1.png"></img>
</div>
</body>
</html>

3.ThymeleafUtils工具类

用户获取html模板和交互数据

import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;

import java.util.Map;

public class ThymeleafUtils {
    /**
     * 服务端动态渲染html文件,并返回渲染后的html字符串
     * @param path  需要渲染的html文件路径 如:"template/xxx/xxx.html"
     * @param params 要传递的参数
     * @return
     */
    public static String getHtmlBody(String path, Map<String,Object> params) {
        TemplateEngine templateEngine = new SpringTemplateEngine();
        // 1.读取磁盘中的模板文件,设置引擎使用resolver
        ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver();
        templateEngine.setTemplateResolver(resolver);
        // 2. 设置映射数据
        // 1. 利用thymeleaf中Context对象,存储模板中所用到的值
        Context context = new Context();
        context.setVariables(params);
        //3.使用thymeleaf 向html文件内赋值,并获取渲染后的html代码
        String content = templateEngine.process("templates/"+path,context);
        return content;
    }
}

4.创建itextpdf工具类HtmlToPdf

将HTML内容转为pdf,方法内有转为字节的,也有直接给路径写出PDF文件的,因为itextpdf默认是不支持中文的,需要手动加载中文。

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.annotation.PostConstruct;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;

@Component
public class HtmlToPdf {

    @Value("${imagePath}")
    private String imagePath;

    public static String IMAGE_PATH;

    private static final String FONT1 = "templates/方正兰亭细黑_GBK.TTF";
    private static final String FONT2 = "templates/方正兰亭中黑_GBK.TTF";

    @PostConstruct
    public void init(){
        IMAGE_PATH = this.imagePath;
    }

    /**
     * 生成pdf
     * @param content html内容
     * @param newFile 路径
     * @throws Exception
     */
    public static void createPdf(String content,String newFile) throws Exception{
        ITextRenderer render = new ITextRenderer();
        ITextFontResolver fontResolver = render.getFontResolver();
        fontResolver.addFont(FONT1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        fontResolver.addFont(FONT2, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 解析html生成pdf
        render.setDocumentFromString(content);
        //解决图片相对路径的问题
        render.getSharedContext().setBaseURL("file:"+IMAGE_PATH);
        render.layout();
        render.createPDF(new FileOutputStream(newFile));

    }

    /**
     * 生成pdf
     * @param content htm内容
     * @return pdf流
     * @throws Exception
     */
    public static byte[] createPdf(String content) throws Exception{
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            ITextRenderer render = new ITextRenderer();
            ITextFontResolver fontResolver = render.getFontResolver();
            fontResolver.addFont(FONT1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            fontResolver.addFont(FONT2, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            // 解析html生成pdf
            render.setDocumentFromString(content);
            //解决图片相对路径的问题
            render.getSharedContext().setBaseURL("file:"+IMAGE_PATH);
            render.layout();
            render.createPDF(outputStream);
        }catch (Exception e){
            e.printStackTrace();
        }

        return outputStream.toByteArray();

    }

    /**
     * 合并pdf
     * @param bytes
     * @param newFile
     */
    public static void mergePdfFiles(List<byte[]> bytes, String newFile) {
        try {
            // 以第一个pdf作为基础,后面的每页信息逐渐累加
            Document document = new Document(new PdfReader(bytes.get(0)).getPageSize(1));
            PdfCopy copy = new PdfCopy(document, new FileOutputStream(newFile));
            document.open();
            for (byte[] aByte : bytes) {
                PdfReader reader = new PdfReader(aByte);
                int n = reader.getNumberOfPages();
                for (int j = 1; j <= n; j++) {
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, j);
                    copy.addPage(page);
                }
            }
            document.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
    }

    /**
     * 合并pdf
     * @param bytes
     */
    public static  byte[] mergePdfFiles(List<byte[]> bytes) {
        ByteArrayOutputStream outputStream = null;
        try {
            outputStream = new ByteArrayOutputStream();
            // 以第一个pdf作为基础,后面的每页信息逐渐累加
            Document document = new Document(new PdfReader(bytes.get(0)).getPageSize(1));
            PdfCopy copy = new PdfCopy(document, outputStream);
            document.open();
            for (byte[] aByte : bytes) {
                PdfReader reader = new PdfReader(aByte);
                int n = reader.getNumberOfPages();
                for (int j = 1; j <= n; j++) {
                    document.newPage();
                    PdfImportedPage page = copy.getImportedPage(reader, j);
                    copy.addPage(page);
                }
            }
            document.close();
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
        return outputStream.toByteArray();
    }
}
①.图片资源处理:

1.网络图片,

2.服务器资源图片,需要指定路径render.getSharedContext().setBaseURL("file:/home/image/");

3.base64图片

4.项目内图片,获取图片后转base64

ClassPathResource classPathResource = new ClassPathResource("static/images/1.jpg");
//绝对路径
classPathResource.getFile().getPath()
②多页PDF处理

使用mergePdfFiles方法可以对多个PDF流合并

5.使用

Map<String,Object> map = new HashMap<>();
String start = ThymeleafUtils.getHtmlBody("/1.html",map);
byte[] pdfByte = HtmlToPdf.createPdf(start);

  • 12
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值