简单使用Itext和Freemarker将HTML转为PDF

本文介绍了如何结合Itext和Freemarker库将HTML内容转换成PDF文档。首先,添加了必要的Maven依赖;接着,准备了FTL模板文件和中文字体MicrosoftYaHei.ttf;然后,展示了生成PDF的代码示例,特别强调了代码需根据实际需求调整;最后,可以查看生成的PDF文档。

1、添加maven依赖

<!-- itext -->
<dependency>
    <groupId>com.lowagie</groupId>
    <artifactId>itext</artifactId>
    <version>2.1.0</version>
</dependency>
<!-- renderer -->
<dependency>
    <groupId>org.xhtmlrenderer</groupId>
    <artifactId>core-renderer</artifactId>
    <version>R8</version>
</dependency>
<!--freemarker-->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.28</version>
</dependency>
<!-- hutool 用到了模板引擎和工具类 -->
<!-- 官方文档:https://www.javajike.com/book/hutool/chapter13/8601729e6eee0c3a901fc95a303d639d.html -->
<!-- 官方API文档:https://apidoc.gitee.com/loolly/hutool/ -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>4.1.0</version>
</dependency>
<!-- commons-text 用到反转义-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.8</version>
</dependency>
<!-- guava 用了一些工具方法-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

2、准备模板文件和字体文件

  • 模板文件 demo.ftl
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"></meta>
    <title>Title</title>
</head>
<body style = 'font-family:Microsoft YaHei;'>
<h1>PDF Demo</h1>
<h3>${user.name!'未知'}</h3>
<h3>${user.age!'未知'}</h3>
<h3>${user.gender!'未知'}</h3>
</body>
</html>
  • 字体文件 MicrosoftYaHei.ttf,百度下载一个吧,商用的话应该需授权...

3、生成PDF代码

支持中文。实际使用需注意 自定义的模板文件字体文件填充的数据,并对下方示例代码进行修改和封装。

package com.example.demo.test;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.template.Engine;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.text.StringEscapeUtils;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Slf4j
public class Demo {

    //PDF保存路径
    public static String pdf_save_path = "/opt/demo/pdf/export/";
    //PDF字体路径
    public static String pdf_font_path = "/opt/demo/pdf/tmpl/font/MicrosoftYaHei.ttf";
    //模板路径
    public static String pdf_tmpl_path = "/opt/demo/pdf/tmpl/";
    //模板名称
    public static String pdf_tmpl_name = "demo.ftl";
    //PDF加密密钥
    public static String pdf_secret = "qwe123!@#.";

    public static void main(String[] args) {
        //读取模板
        Engine engine = TemplateUtil.createEngine(new TemplateConfig(pdf_tmpl_path, TemplateConfig.ResourceMode.FILE));
        Template template = engine.getTemplate(pdf_tmpl_name);

        HashMap<String, Object> data = Maps.newHashMap();
        //添加数据
        HashMap<String, Object> user = Maps.newHashMap();
        user.put("name","admin");
        user.put("age","18");
        user.put("gender","男");
        data.put("user",user);

        //根据模板和数据生成html
        String html = template.render(data);
        //对html内容进行反转义,例如将&ldquo;和&rdquo;转为双引号,防止XML解析异常
        html = StringEscapeUtils.unescapeHtml4(html);

        String fileName = "demo.pdf";
        try (BufferedOutputStream out = FileUtil.getOutputStream(pdf_save_path + fileName);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            ITextRenderer iTextRenderer = new ITextRenderer();
            iTextRenderer.getFontResolver().addFont(pdf_font_path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
            iTextRenderer.setDocumentFromString(html);
            iTextRenderer.layout();
            iTextRenderer.createPDF(baos);
            iTextRenderer.finishPDF();
            //添加水印(可添加多个)
            ArrayList<String> texts = Lists.newArrayList(DateUtil.now(), "我是水印1", "我是水印2");
            InputStream in = new ByteArrayInputStream(baos.toByteArray());
            baos.flush();
            addWaterMark(in, out, texts);
            System.out.println("success!");
        } catch (Exception e) {
            log.error("=====创建pdf异常:", e);
        }
    }

    /**
     * 添加水印
     *
     * @param arr
     */
    public static void addWaterMark(InputStream in, OutputStream out, List<String> arr) throws DocumentException, IOException {
        PdfReader pdfReader = new PdfReader(in);
        PdfStamper pdfStamper = new PdfStamper(pdfReader, out);
        pdfStamper.setEncryption(null, pdf_secret.getBytes(), PdfWriter.ENCRYPTION_AES_128, false);
        int pages = pdfReader.getNumberOfPages() + 1;
        // 设置水印透明度
        PdfGState gs = new PdfGState();
        gs.setFillOpacity(0.3f);
        for (int i = 1; i < pages; i++) {
            PdfContentByte underContent = pdfStamper.getOverContent(i);
            underContent.beginText();
            underContent.setFontAndSize(BaseFont.createFont(pdf_font_path, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED), 12);
            underContent.setGState(gs);
            underContent.setColorFill(Color.blue);
            for (int m = 0; m < 6; m++) {
                for (int j = 0; j < 6; j++) {
                    for (int n = 0; n < arr.size(); n++) {
                        underContent.showTextAlignedKerned(Element.ALIGN_LEFT, arr.get(n), 100 * j, (n + 1) * 20 + 200 * m, 45);
                    }
                }
            }
            underContent.endText();
            underContent.stroke();
        }
        pdfStamper.close();
        pdfReader.close();
    }
}

4、查看PDF

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值