SpringBoot 基于iText 根据PDF模板动态生成文件

news2024/11/25 12:07:06

SpringBoot 基于iText 根据PDF模板动态生成文件, 需要使用 adobe acrobat pro DC这个工具来自定义模板
支持根据PDF模板生成单页或多页PDF文件

adobe acrobat pro DC 自定义模板

下载地址

链接:https://pan.baidu.com/s/1Vn3bIQ5_D17sEZnkF2t7gg?pwd=n6o1 
提取码:n6o1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加依赖

 <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>

代码集成


import cn.hutool.core.io.resource.ClassPathResource;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;

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

/**
 * @author wang
 */
@Slf4j
public class PdfUtil {

    private PdfUtil() {

    }

    /**
     * generatePdf
     * @param params    params
     * @param outputPath    outputPath
     * @return  String
     */
    public static String generatePdf(Map<String, String> params, String outputPath) {
        ClassPathResource resource = new ClassPathResource("templates/test_certificate_temp.pdf");
        InputStream inputStream = resource.getStream();
        ByteArrayOutputStream bos = null;
        PdfReader reader = null;
        FileOutputStream fos = null;
        try {
            reader = new PdfReader(inputStream);
            bos = new ByteArrayOutputStream();
            writePdf(params, bos, reader);
            fos = new FileOutputStream(outputPath);
            bos.writeTo(fos);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        } finally {
            try {
                assert bos != null;
                bos.close();
                reader.close();
                assert fos != null;
                fos.close();
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        }
        return outputPath;
    }

    /**
     * generateMultiPagePdf
     *
     * @param paramsList paramsList
     * @param outputPath outputPath
     * @return String
     */
    public static String generateMultiPagePdf(List<Map<String, String>> paramsList, String outputPath) {
        FileOutputStream fos = null;
        PdfCopy copy = null;
        Document document = null;

        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream("templates/test_certificate_temp.pdf");

            // 将模板读取到字节数组中
            assert inputStream != null;
            byte[] templateBytes = inputStream.readAllBytes();
            inputStream.close();

            fos = new FileOutputStream(outputPath);
            document = new Document();
            copy = new PdfCopy(document, fos);
            document.open();

            for (Map<String, String> params : paramsList) {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                InputStream templateStream = new ByteArrayInputStream(templateBytes);
                PdfReader reader = new PdfReader(templateStream);
                writePdf(params, bos, reader);
                reader.close();
                templateStream.close();

                PdfReader pageReader = new PdfReader(new ByteArrayInputStream(bos.toByteArray()));
                copy.addPage(copy.getImportedPage(pageReader, 1));
                pageReader.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (document != null) {
                    document.close();
                }
                if (copy != null) {
                    copy.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return outputPath;
    }

    private static void writePdf(Map<String, String> params, ByteArrayOutputStream bos, PdfReader reader) throws DocumentException, IOException {
        PdfStamper pdfStamper = new PdfStamper(reader, bos);
        AcroFields acroFields = pdfStamper.getAcroFields();
        BaseFont font = BaseFont.createFont();
        for (Map.Entry<String, String> param : params.entrySet()) {
            acroFields.setFieldProperty(param.getKey(), "textfont", font, null);
            acroFields.setField(param.getKey(), param.getValue());
        }
        pdfStamper.setFormFlattening(true);
        pdfStamper.close();
    }

    public static void main(String[] args) throws IOException {
        List<Map<String, String>> paramsList = new ArrayList<>();
        Map<String, String> params = new HashMap<>(16);
        params.put("hullId", "hullId_001");
        params.put("boatYear", "boatYear_001");
        params.put("boatBrand", "boatBrand_001");
        params.put("boatModel", "boatModel_001");
        paramsList.add(params);

        params = new HashMap<>(16);
        params.put("hullId", "hullId_002");
        params.put("boatYear", "boatYear_002");
        params.put("boatBrand", "boatBrand_002");
        params.put("boatModel", "boatModel_002");
        paramsList.add(params);

        String outputPath = "D:\\opt\\file_encode_zip\\target\\test_Certificate_8-20-24_target.pdf";
        String path = generateMultiPagePdf(paramsList, outputPath);
//        String path = generatePdf(params, outputPath);
        System.out.println(path);

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086618.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【hot100篇-python刷题记录】【杨辉三角】

R6-dp篇 印象题&#xff0c;但做法应该改变了 思路&#xff1a;前两行直接写 next[i]cur[i-1]cur[i]&#xff0c;其中next[0]和next[-1] 这样的话&#xff0c;需要创建2个额外的数组空间&#xff0c;而且还要变化 所以考虑动态规划 class Solution:def generate(self, num…

Efficient LoFTR论文阅读(特征匹配)

Efficient LoFTR论文阅读&#xff08;特征匹配&#xff09; 摘要1. 引言2. 相关工作基于检测器的图像匹配无检测器图像匹配 3. 方法3.1. 局部特征提取3.2. 高效的局部特征变换3.3. 准备工作3.4. 聚合注意力机制3.5 粗级匹配模块有效推理策略子像素级细化模块有效的精细特征提取…

[C语言]一、C语言基础(03.函数)

G:\Cpp\C语言精讲 6. 函数 6.1函数的基本使用 6.1.1 为什么需要函数 《街霸》游戏中&#xff0c;每次人物出拳、出脚或跳跃等动作都需要编写50-80行的代码&#xff0c;在每次出拳、出脚或跳跃的地方都需要重复地编写这50-80行代码&#xff0c;这样程序会变得很臃肿&#xff…

目前kimi算不算国内顶级的AI?

利用AI工具批量生成影视短剧推广https://docs.qq.com/doc/DYnl6d0FLdHp0V2ll 从用户体验上讲&#xff0c;我觉得 Kimi 算得上国内的顶级 AI。 现在的大模型产品遍地开花&#xff0c;底层模型原理差异不大&#xff0c;想要在这样的市场环境中生存下来并赢得普通用户认可&#xf…

Go锁 详解

锁 - Go 函数并发编程中&#xff0c;锁是一种同步机制&#xff0c;用于协调对共享资源的访问&#xff0c;防止数据竞争 - Go 中提供了多种类型的锁&#xff0c;每种锁都有不同的特性和适用场景类型 互斥锁&#xff08;mutex&#xff09; 基础锁&#xff0c;只能同时允许一个 g…

【C++ Primer Plus习题】6.5

问题: 解答: #include <iostream> using namespace std;int main() {float salary 0;float tax 0;while (salary>0){cout << "请输入您的工资:";cin >> salary;if (cin.fail())break;if (salary < 5000){tax 0;}else if (salary < 15…

2024 MongoDB中国用户大会倒计时2天!请查收专属参会指南

距离2024 MongoDB中国用户大会即将开幕仅剩2天&#xff0c;我们非常期待与您共同探讨和分享最新的数据库技术与应用经验。为了确保您能够顺利参与本次会议&#xff0c;请查阅属于您的专属温馨提示&#xff01; 活动时间 8月31日09:00-17:30 签到开始&#xff1a;08:00 现场参…

Linux实现异步IO的方法:epoll,posix aio,libaio,io_uring

Linux中异步IO的实现方式大概有以下几种&#xff1a; 1. epoll 熟悉网络编程的人可能会想到select&#xff0c;poll&#xff0c;epoll这些异步IO的方式&#xff0c;但实际上这些方式叫做非阻塞IO&#xff0c;并不是实际意义上的异步IO。因此这些只能用于异步的Socket IO&…

Xline v0.7.0: 一个用于元数据管理的分布式KV存储

Xline是什么&#xff1f;我们为什么要做Xline&#xff1f; Xline是一个基于Curp协议的&#xff0c;用于管理元数据的分布式KV存储。现有的分布式KV存储大多采用Raft共识协议&#xff0c;需要两次RTT才能完成一次请求。当部署在单个数据中心时&#xff0c;节点之间的延迟较低&a…

【C++从小白到大牛】C++的隐式和显示类型转换基础知识讲解

目录 1、C语言中的类型转换 2、C语言和C中可以相互转换的类型总结 C语言&#xff1a; CPP&#xff1a; 3. 为什么C需要四种类型转换 4、C四大强制类型转换 4.1static_cast 4.2 reinterpret_cast 4.3 const_cast 4.4dynamic_cast 注…

吴恩达机器学习笔记 四十五 基于内容的过滤的tensorFlow实现

一个user网络&#xff0c;一个item网络 &#xff0c;使用顺序模型&#xff0c;激活函数选择relu&#xff0c;最后的输出大小都是32。 input_user提取特征&#xff0c;然后把这些特征送给上面的user_NN这个网络得到用户向量vu&#xff0c;再对vu进行标准化&#xff08;用l2范式&…

【最精简】解决访问GitHub慢的问题

我们通过命令行ping两个网站获取对应的IP地址 在windows中&#xff0c;修改hosts文件&#xff0c;路径一般是C:\Windows\System32\drivers\etc&#xff0c;用记事本打开&#xff0c;输入以下内容即可。 // 配置GitHub加速 199.232.69.194 github.global.ssl.fastly.net 140.8…

数据结构与算法 第3天(栈和队列)

栈和队列也是线性表&#xff0c;限制插入和删除的位置只能在端点 栈&#xff08;stack&#xff09; 后进先出 LIFO 表尾进入&#xff0c;表尾删除 一、案例 案例一&#xff1a;进制转换 例子 159转换成八进制 159/819...7 19/82...3 2/80...2 结果为237 案例二&#xff1a;括…

【香橙派系列教程】(二十) 系统移植、交叉编译工具链—OrangePi Zero2 SDK说明

【二十】基于OrangePi Zero2的系统移植—OrangePi Zero2 SDK说明 文章目录 【二十】基于OrangePi Zero2的系统移植—OrangePi Zero2 SDK说明1.使用环境要求2.Linux获取SDK3.首次编译完整SDK 之前我们在使用香橙派时&#xff0c; 都是直接在香橙派上进行代码编译&#xff0c; 但…

联华证券-新手炒股入门指南:学习路径与注意事项

学习炒股是一个循序渐进的过程&#xff0c;以下是入门建议以及需要注意的事项&#xff1a; 学习炒股的入手步骤 掌握基础知识&#xff1a; 股票市场基础&#xff1a;了解什么是股票、股市的运作机制、股票的种类等基本概念。 常用术语&#xff1a;熟悉如市盈率&#xff08;P/…

8.29c++

仿照string类&#xff0c;实现myString #include <iostream> #include <cstring> using namespace std; class myString { public://无参构造myString():size(10){strnew char[size];//堆区创建空间}//有参构造myString(const char *s){sizestrlen(s);//获取长度s…

TeamTalk消息服务器学习

msg_server发送消息 信令 //service id 0x0003 message IMMsgData{//cmd id: 0x0301required uint32 from_user_id 1; //消息发送方required uint32 to_session_id 2; //消息接受方required uint32 msg_id 3; // 非常重要&#xff1a;由谁产生&#xff1f;答&…

ShenNiusModularity项目源码学习(2:登录页面验证码)

前端登录页面Login.cshtml位于ShenNius.Admin.Mvc项目的Areas\Sys\Views\User内&#xff0c;页面中使用的验证码是调用同项目内UserController的OnGetVCode函数获取验证码图片。   点击验证码图片&#xff0c;会调用wwwroot\js\login.js定义的changeSrcCode函数刷新验证码。…

Qt调用外部exe并嵌入到Qt界面中(验证成功的成功)

http://t.csdnimg.cn/CDsqQ 原作者在这里 本文章主要介绍如何用Qt调用其他应用的exe,并将窗口嵌入到Qt界面中。很多人查到的代码都能成功的将exe调用起来&#xff0c;但是嵌入不到窗口中。主要有两种原因&#xff0c;现在从头到尾的梳理一下。 1.主要代码 1.1启动exe //包含…

keil编译输出的信息program size含义,以及个人使用中的编译内存溢出问题

keil编译后输出的信息含义 data对应的是片内的RAM&#xff0c;xdata对应的是程序中片外扩展的存储器上需要占用的容量&#xff0c;code是编写的程序占用单片机片内的存储程序ROM上的容量。 编译中发现错误 上图中的data值占用了147字节&#xff0c;超过了128字节。 一般解决…