HTML转PDF

917 阅读3分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战」。

前言

最近接到一个需求,网站提供一个模板,然后用户下载模板,下载的时候自动填充上用户的一些信息,比如姓名,当前日期等。并且下载后的模板文件为PDF格式。

方案一

前端写一个模板页面,后端返回需要的一些数据,由前端拿到数据去替换模板上的数据,用户通过浏览器自带的打印,可以直接下载打印。操作大体步骤应该是用户点击下载按钮,然后弹出下面界面,用户可以打印或者另存为PDF image.png 这个方案比较简单,而且没有什么难点。但是有一个问题,不同浏览器的效果不一样,拿谷歌为例,用户点击后跳转到上述页面,用户可以先保存下来,再去打印,然后盖章,签字再上传,而火狐浏览器,点击打印的时候只有打印按钮,没有另存为PDF,那么就要求用户必须连接了打印机,这并不现实。所以这个方案并不合适。

方案二

既然前端没法做到统一出口,拿生成PDF就只能放在后端去完成,网上搜集了很多资料,最后方案为:

  • 前端写好html模板页面,当作静态资源存放,因为一般不会修改
  • 后端拿到html,替换掉需要填充信息的占位符
  • 后端把填充完信息的html转为pdf返回给前端,完成下载 那么重点就是 html 转成 pdf 怎么实现?

最终决定使用iText插件完成

这是一个能够快速产生 PDF 文件的 Java 类库

选择原因

  • 免费
  • 无需额外安装应用
  • java编写,跨平台,整合简单

整合代码示例

  1. 引入依赖
<!--pdf 转换-->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.1.17</version>
    <type>pom</type>
</dependency>
<!-- html转pdf依赖 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>html2pdf</artifactId>
    <version>3.0.5</version>
</dependency>
<!--  html 解析工具类 -->
<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.13.1</version>
</dependency>
<!--pdf end-->

这里多引入了一个JSOUP库,这个是一个便于Java解析操作html的类库,就类似于把一个Html文件转化成我们熟悉的java对象,我们可以方便的操作html的每个节点,如同操作对象的属性方法一样。

测试类

@Test
public void testHtml2Pdf() {
    try {
        // 生成pdf保存的位置
        String pdfPath = "C:/Users/Administrator/Desktop/aa.pdf";
        PdfWriter pdfWriter = new PdfWriter(new File(pdfPath));
        // 生成pdf文档对象
        PdfDocument pdfDocument = new PdfDocument(pdfWriter);
        // 可以设置文档大小,等等
        pdfDocument.setDefaultPageSize(PageSize.A4);
        // 设置转换时的一些参数设置,比如字体等
        ConverterProperties pro = new ConverterProperties();
        // itext没有提供现成的中文字体,我们需要自己加载字体库
        FontProvider fontProvider = new DefaultFontProvider();
        // 我们直接引用系统的字体库
        fontProvider.addSystemFonts();
        pro.setFontProvider(fontProvider);
        // 读取我们的模板然后转化成pdf
        HtmlConverter.convertToPdf(new FileInputStream("./src/main/resources/template/authTemplate.html"), pdfDocument, pro);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>xxx商城账户认证公函</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC:100,300,400,500,700,900">
</head>
<body>
<h1 align="center" style="text-align:center; margin-top:23px; margin-bottom:22px"><span style="font-size:22pt"><span
        style="line-height:240%"><span><span style="font-weight:bold"><b><span style="font-size:22.0000pt"><span><span
        style="font-weight:bold;font-family:'Noto Sans SC';">xxx商城账户认证公函</span></span></span></b></span></span></span></span>
</h1>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span style="font-size:10.5000pt"><span><font
        face="Calibri">______________:</font></span></span></span></span></p>

<p style="text-align:justify">&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span style="font-size:10.5000pt"><span>账户<font
        face="Calibri">_____________,UID______________,</font><font face="宋体">申请认证为</font><font face="Calibri">__________________-</font><font
        face="宋体">在xxx商城(</font><font face="Calibri">wwwxxxxxxcom</font><font face="宋体">)的采购身份认证,用户完成认证之后可以以贵司身份在平台系统中进行询价下单等功能的使用。</font></span></span></span></span>
</p>

<p style="text-align:justify">&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span
        style="font-size:10.5000pt"><span>申明:</span></span></span></span></p>

<ol>
    <li style="text-align:justify"><span style="font-size:10.5pt"><span><span style="font-size:10.5000pt"><span>账号的所有权归注册用户所有,账户中创建的与贵司关联的单据归贵司所有,贵司可以随时停止向当前用户的授权,可以通过联系我司客服或者注册账号并认证为管理员账号,进行对已授权用户进行屏蔽处理。</span></span></span></span>
    </li>
    <li style="text-align:justify"><span style="font-size:10.5pt"><span><span style="font-size:10.5000pt"><span>公司停止对用户授权或者屏蔽处理之后,当前认证的账号的认证会被取消,同时当前账户创建的关于贵司的单据都将没有权限查看,如果需要单据信息可以登录公司管理员账号进行查看。</span></span></span></span>
    </li>
</ol>

<p style="text-align:justify">&nbsp;</p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span
        style="font-size:10.5000pt"><span>单 位 盖 章:</span></span></span></span></p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span
        style="font-size:10.5000pt"><span>申请人 签字:</span></span></span></span></p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span
        style="font-size:10.5000pt"><span>联 系 电 话:</span></span></span></span></p>

<p style="text-align:justify"><span style="font-size:10.5pt"><span><span style="font-size:10.5000pt"><span>申 请 日 期:<font
        face="Calibri">2022</font><font face="宋体"></font><font face="Calibri">1</font><font face="宋体"></font><font
        face="Calibri">1</font><font face="宋体"></font></span></span></span></span></p>

</body>
</html>

运行后桌面生成了我们需要的pdf文件。

image.png

因为篇幅有限,这里我就不写具体参数替换的方法了,后面有时间补一下。