iText通过FreeMarker模板生成PDF解决方案

首先定义一个HTML模板,通过后台数据填充,生成PDF文件。

目录

一、所需依赖 

二、生成工具类

三、准备模板

四、 字体和模板放置的位置

五、生成PDF文件预览


一、所需依赖 

<!--    pdf所需依赖模块begin-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
        </dependency>


        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.11</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.19</version>
        </dependency>
        <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>
        <!--    pdf所需依赖模块end-->
   
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.16</version>
        </dependency>

二、生成工具类

package com.ruoyi.print_system.util;

import cn.hutool.core.io.resource.ResourceUtil;
import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;

import java.io.*;
import java.util.Map;


public class JavaToPdfUtil {

    private static Logger logger = LoggerFactory.getLogger(JavaToPdfUtil.class);

    //模板文件
    private static final String HTML = "template/pdf-template.html";
    //仿宋字体
    private static final String FONT_TTF = "fonts/FangSong.ttf";

    private static Configuration freemarkerCfg = null;

    static {
        freemarkerCfg = new Configuration();
        //freemarker的模板目录
        try {
            freemarkerCfg.setDirectoryForTemplateLoading(new File(ResourceUtil.getResource("").getPath()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建PDF文件
     *
     * @param data     数据加载
     * @param filename 文件名称
     * @return
     */
    public static boolean createPdfFile(Map<String, Object> data, String filename) {
        try {
            String content = JavaToPdfUtil.freeMarkerRender(data, HTML);
            JavaToPdfUtil.createPdf(content, filename);
            logger.info("PDF生成成功");
        } catch (Exception e) {
            logger.error("PDF生成失败:{}", e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * freemarker渲染html
     */
    public static String freeMarkerRender(Map<String, Object> data, String htmlTmp) {
        Writer out = new StringWriter();
        try {
            // 获取模板,并设置编码方式
            Template template = freemarkerCfg.getTemplate(htmlTmp);
            template.setEncoding("UTF-8");
            // 合并数据模型与模板
            template.process(data, out); //将合并后的数据和模板写入到流中,这里使用的字符流
            out.flush();
            return out.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    /**
     * html生成PDF文件
     *
     * @param content 渲染后的html字符串
     * @param dest    PDF生成路径地址
     * @throws Exception
     */
    public static void createPdf(String content, String dest) throws Exception {
        ITextRenderer render = new ITextRenderer();
        ITextFontResolver fontResolver = render.getFontResolver();
        // 解决itext生成中文不显示问题
        String FONT_TTF_PATH = ResourceUtil.getResource("").getPath().replace("target/classes/", "").concat("src/main/resources/") + FONT_TTF;
        fontResolver.addFont(FONT_TTF_PATH, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        // 解析html生成pdf
        render.setDocumentFromString(content);
        //解决图片相对路径的问题
        render.getSharedContext().setBaseURL(null);
        render.layout();
        render.createPDF(new FileOutputStream(dest));
    }


}

三、准备模板

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>Document</title>
    <style>
        <!-- A4纸张横向显示       -->
        @page {
            size: 297mm 210mm;
        }

        body {
            /*中文字体*/
            font-family: FangSong;
        }

        #main {
            font-size: 20px;
            width: 843px;
            height: 596px;
            margin-left: 20px;
        }


        #photo {
            width: 95px;
            height: 130px;
            position: absolute;
            left: 532px;
            top: 100px;
        }

        #left {
            width: 330px;
            height: 270px;
            position: relative;
            left: 0px;
            top: 160px;
            text-align: left;
            padding: 5px;
        }

        #left>p {
            text-indent: 2em;
        }

        #left p:nth-child(1) {
            line-height: 30px;
        }

        #left p:nth-child(2) {
            line-height: 20px;
            font-size: 16px;
            /*英文字体*/
            font-family: "PmingLiu";
        }

        #left p:nth-child(3) {

            position: relative;
            left: 100px;
            top: 25px;
        }

        #right {
            width: 300px;
            height: 320px;
            float: right;
            position: relative;
            right: 150px;
            bottom: 120px;
        }

        #right>p {
            text-align: center;
        }

        #right p:nth-child(1) {
            position: relative;
            top: 18px;
            left: 0;

        }

        #right p:nth-child(2) {
            position: relative;
            top: 24px;
            left: 0;
        }

        #right p:nth-child(3) {
            position: relative;
            top: 28px;
            left: 0;
        }

        #right p:nth-child(4) {
            position: relative;
            top: 30px
        }

        #right p:nth-child(5) {
            position: relative;
            top: 36px;
            left: 15px;
        }

        #right p:nth-child(6) {
            position: relative;
            top: 42px;
            left: 15px;
        }

        #right p:nth-child(7) {
            position: relative;
            top: 47px;
            left: 15px;
        }

        a {
            text-decoration: underline;
            color: black;
        }
    </style>
</head>

<body>
    <div id="main">
        <div id="left">
            <p>
                本证书由<a>${evaluationOrganization!''}</a>颁发,表明持证人通过本机构组织的职业技能等级认证,具备该职业
                ${occupationName!''}相应技能等级水平。
            </p>
            <p>
                This is to certify that the bearer has demonstrated
                corresponding competency in this occupation
                (${occupationEnName!''}) for successful compaction of the
                occupational skill Level assessment organized by
                <a>${evaluationOrganizationEn!''}</a>
            </p>
            <p>
                ${evaluationOrganization}<br />发证日期:${certificateDate!''}
            </p>
        </div>
        <img src="${imgUrl}" id="photo" />
        <div id="right">
            <p>${name!''}</p>
            <p>${certificatesType!''}</p>
            <p>${certificatesCode!''}</p>
            <p>${occupationName!''}</p>
            <p>${worktypeName!''}</p>
            <p>${skillLevel!''}</p>
            <p>${certificateNo!''}</p>
        </div>
    </div>
</body>

</html>

四、 字体和模板放置的位置

工程使用的是springboot,所以将资源文件放置在src/main/resources下。

五、生成PDF文件预览

 

作者:YangRoc

出处:https://www.cnblogs.com/YangRoc/p/17186434.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   Roc-xb  阅读(202)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!

易微帮源码


易微帮官网

more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示