基于IText7 PDF模板填充?

2023-12-10 01:01
文章标签 模板 pdf itext7 填充

本文主要是介绍基于IText7 PDF模板填充?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引入依赖

<dependency><groupId>com.itextpdf</groupId><artifactId>itext7-core</artifactId><version>8.0.1</version><type>pom</type>
</dependency>
<dependency><groupId>com.itextpdf</groupId><artifactId>bouncy-castle-adapter</artifactId><version>8.0.1</version>
</dependency>

模板填充工具

import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormCreator;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.*;
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
import com.itextpdf.kernel.pdf.annot.PdfWidgetAnnotation;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.muchenx.util.ImageCompressUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;/*** PDF 模板填充工具类(itext7)* <p>* 支持文本 及 图片 填充*/
@Slf4j
public final class PDFTemplateFillHandler {/*** 待填充的PDF模板文档*/private final transient PdfDocument templateDocument;/*** 填充后PDF文档数据*/private final transient ByteArrayOutputStream destByteOutStream;/*** 字体*/private transient PdfFont font;private PDFTemplateFillHandler(PdfDocument templateDocument, ByteArrayOutputStream destByteOutStream) {this.templateDocument = templateDocument;this.destByteOutStream = destByteOutStream;try {this.font = loadFont();} catch (IOException e) {log.warn("加载指定字体异常:{}", e.getMessage());}}public static PDFTemplateFillHandler loadTemplate(InputStream templateFileStream) {try {ByteArrayOutputStream dest = new ByteArrayOutputStream();PdfDocument pdfDocument = new PdfDocument(new PdfReader(templateFileStream), new PdfWriter(dest));return new PDFTemplateFillHandler(pdfDocument, dest);} catch (IOException e) {throw new RuntimeException(e);}}/*** 填充及返回填充后的数据** @param fillData - 待填充数据* @return - 填充后bytes数据*/public byte[] fill(Map<String, Object> fillData) {try {PdfAcroForm form = PdfAcroForm.getAcroForm(templateDocument, true);fillData.forEach((keyword, value) -> {Optional.ofNullable(form.getField(keyword)).ifPresent(templateFormField -> {if (value instanceof byte[]) {PdfArray pos = templateFormField.getWidgets().get(0).getRectangle();float x = pos.getAsNumber(0).floatValue();float y = pos.getAsNumber(1).floatValue();float width = pos.getAsNumber(2).floatValue() - x;float height = pos.getAsNumber(3).floatValue() - y;Rectangle rectangle = new Rectangle(x, y, width, height);PdfWidgetAnnotation widget = new PdfWidgetAnnotation(rectangle);PdfFormField formField = PdfFormCreator.createFormField(widget, templateDocument);PdfPage annotationPage = findAnnotationPage(keyword);if (annotationPage != null) {doFillFieldImage(annotationPage, formField, (byte[]) value);}} else {templateFormField.setValue(String.valueOf(value));if (font != null) {templateFormField.setFont(templateFormField.getFont());}}form.partialFormFlattening(keyword);});});form.flattenFields();} finally {if (templateDocument != null) {templateDocument.close();}}return destByteOutStream.toByteArray();}/*** 图片填充** @param newPage   - 当前页* @param formField - 表单文本域* @param imgBytes  - 图片文件字节数组*/private void doFillFieldImage(PdfPage newPage, PdfFormField formField, byte[] imgBytes) {Rectangle rtl = formField.getWidgets().get(0).getRectangle().toRectangle(); // 获取表单域的xy坐标PdfCanvas canvas = new PdfCanvas(newPage);ImageData img = ImageDataFactory.create(imgBytes);if (Float.compare(img.getWidth(), rtl.getWidth()) <= 0 && Float.compare(img.getHeight(), rtl.getHeight()) <= 0) {// 不处理canvas.addImageAt(img, rtl.getX(), rtl.getY(), true);} else {// 压缩图片。计算得到图片放缩的最大比例float scale = Math.max(img.getWidth() / rtl.getWidth(), img.getHeight() / rtl.getHeight());int imgWidth = Math.round(img.getWidth() / scale);int imgHeight = Math.round(img.getHeight() / scale);// 压缩图片byte[] compressImgBytes;try {compressImgBytes = ImageCompressUtils.resizeByThumbnails(imgBytes, imgWidth, imgHeight);} catch (IOException e) {throw new RuntimeException(e);}img = ImageDataFactory.create(compressImgBytes);canvas.addImageAt(img, rtl.getX(), rtl.getY(), true);}}/*** 根据表单域关键字查找当前关键字所在页对象(PdfPage)** @param keyword - 关键字* @return - page object*/private PdfPage findAnnotationPage(String keyword) {int pages = templateDocument.getNumberOfPages();for (int index = 1; index <= pages; index++) {PdfPage page = templateDocument.getPage(index);for (PdfAnnotation annotation : page.getAnnotations()) {PdfString title = annotation.getPdfObject().getAsString(PdfName.T);if (title != null && keyword.equals(String.valueOf(title))) {return page;}}}return null;}/*** 获取模板文件表单域关键字位置信息*/private Map<Integer, Map<String, float[]>> getFormKeywordsPos() {int pages = templateDocument.getNumberOfPages();Map<Integer, Map<String, float[]>> maps = new HashMap<>(pages);for (int index = 1; index <= pages; index++) {maps.putIfAbsent(index, new HashMap<>());PdfPage page = templateDocument.getPage(index);// 获取当前页的表单域int finalIndex = index;page.getAnnotations().forEach(anno -> {PdfString title = anno.getTitle();PdfArray rectangle = anno.getRectangle();float x = rectangle.getAsNumber(0).floatValue();float y = rectangle.getAsNumber(1).floatValue();float width = rectangle.getAsNumber(2).floatValue() - x;float height = rectangle.getAsNumber(3).floatValue() - y;maps.get(finalIndex).put(title.getValue(), new float[]{x, y, width, height});});}return maps;}/*** 加载字体*/private PdfFont loadFont() throws IOException {Resource[] resources = new PathMatchingResourcePatternResolver().getResources("classpath*:/font/*.ttc");if (resources.length == 0) {return null;}PdfFontFactory.register(resources[0].getURL().getPath(), "SimSun");return PdfFontFactory.createRegisteredFont("SimSun", PdfEncodings.IDENTITY_H,PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED);}
}

填充实例

LocalDate now = LocalDate.now();
// 图片文件
ByteArrayOutputStream catOutStream = new ByteArrayOutputStream();
File img = ResourceUtils.getFile("classpath:cat.png");
InputStream catInStream = Files.newInputStream(img.toPath());
IOUtils.copy(catInStream, catOutStream);
Map<String, Object> data = new HashMap<>();
data.put("username", "喵星人");
data.put("gender", "女");
data.put("nation", "狗");
data.put("school", "狗族大学");
data.put("describe", "千百年来,地球上一直住着一种外星生物,名叫喵星人。它们从遥远的喵星来到地球,化身为猫科动物,分散在世界每个角落。萌萌的外表,加上机智聪明的头脑,轻易就得到人类的宠爱。");
data.put("describe1", "千百年来,地球上一直住着一种外星生物,名叫喵星人。它们从遥远的喵星来到地球,化身为猫科动物,分散在世界每个角落。萌萌的外表,加上机智聪明的头脑,轻易就得到人类的宠爱。");
data.put("content", "千百年来,地球上一直住着一种外星生物,名叫喵星人。它们从遥远的喵星来到地球,化身为猫科动物,分散在世界每个角落。萌萌的外表,加上机智聪明的头脑,轻易就得到人类的宠爱。");
data.put("sign", catOutStream.toByteArray());
data.put("avatar", catOutStream.toByteArray());
data.put("year", String.valueOf(now.getYear()));
data.put("month", String.valueOf(now.getMonthValue()));
data.put("day", String.valueOf(now.getDayOfMonth()));String homePath = FileSystemView.getFileSystemView().getHomeDirectory().getAbsolutePath();
File template = ResourceUtils.getFile("classpath:fill_template.pdf");
byte[] filledDataBytes = PDFTemplateFillHandler.loadTemplate(Files.newInputStream(template.toPath())).fill(data);
IOUtils.write(filledDataBytes, Files.newOutputStream(Paths.get(homePath + "/" + System.nanoTime() + ".pdf")));

基于IText7 的 PDF表单域模板填充

这篇关于基于IText7 PDF模板填充?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/475606

相关文章

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

使用JavaScript将PDF页面中的标注扁平化的操作指南

《使用JavaScript将PDF页面中的标注扁平化的操作指南》扁平化(flatten)操作可以将标注作为矢量图形包含在PDF页面的内容中,使其不可编辑,DynamsoftDocumentViewer... 目录使用Dynamsoft Document Viewer打开一个PDF文件并启用标注添加功能扁平化

使用Python制作一个PDF批量加密工具

《使用Python制作一个PDF批量加密工具》PDF批量加密‌是一种保护PDF文件安全性的方法,通过为多个PDF文件设置相同的密码,防止未经授权的用户访问这些文件,下面我们来看看如何使用Python制... 目录1.简介2.运行效果3.相关源码1.简介一个python写的PDF批量加密工具。PDF批量加密

基于C#实现将图片转换为PDF文档

《基于C#实现将图片转换为PDF文档》将图片(JPG、PNG)转换为PDF文件可以帮助我们更好地保存和分享图片,所以本文将介绍如何使用C#将JPG/PNG图片转换为PDF文档,需要的可以参考下... 目录介绍C# 将单张图片转换为PDF文档C# 将多张图片转换到一个PDF文档介绍将图片(JPG、PNG)转

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc