使用itextPDF实现PDF电子公章工具类

一、制作公章

在线网站:印章生成器 - Kalvin在线工具 (kalvinbg.cn)

然后对公章进行下载保存

盖章图片:

二、生成数字签名

2.1: java工具keytool生成p12数字证书文件

Keytool是用于管理和证书的工具,位于%JAVA_HOME%/bin目录。
使用JDK的keytool工具

  • keytool在jdk的bin目录下

2.2:启动黑窗命令

2.3:生成数字文件

D:\keystore\server.keystore : 就是生成的文件地址

keytool -genkeypair -alias whj -keypass 111111 -storepass 111111 -dname “C=CN,ST=SD,L=QD,O=haier,OU=dev,CN=haier.com” -keyalg RSA -keysize 2048 -validity 3650 -keystore D:\keystore\server.keystore

2.4:转换为p12格式,在命令行输入

注意:这里的路径和上面的路径要保持一直,不能就转不了P12 格式

keytool -importkeystore -srckeystore D:\keystore\server.keystore -destkeystore D:\keystore\whj.p12 -srcalias whj -destalias serverkey -srcstoretype jks -deststoretype pkcs12 -srcstorepass 111111 -deststorepass 111111 -noprompt

三、代码部分

3.1:添加依赖:

      <!-- itextpdf依赖 --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</version></dependency><dependency><!-- 摘要算法 --><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.49</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpkix-jdk15on</artifactId><version>1.49</version></dependency>

3.2:盖章功能工具类

功能:

对传入的pdf 文件进行盖章处理

public class ItextUtil {/**** 功能: keystory密码*/public static final char[] PASSWORD = "111111".toCharArray();/*** 单多次签章通用** @param src 盖章文件路径* @param target 盖章文件输出目标路径* @param signatureInfo 盖章实体*/public void sign(String src, String target, SignatureInfo signatureInfo) {InputStream inputStream = null;FileOutputStream outputStream = null;ByteArrayOutputStream result = new ByteArrayOutputStream();try {inputStream = Files.newInputStream(Paths.get(src));ByteArrayOutputStream tempArrayOutputStream = new ByteArrayOutputStream();PdfReader reader = new PdfReader(inputStream);// 创建签章工具PdfStamper ,最后一个boolean参数是否允许被追加签名// false的话,pdf文件只允许被签名一次,多次签名,最后一次有效// true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改PdfStamper stamper = PdfStamper.createSignature(reader,tempArrayOutputStream, '\0', null, true);// 获取数字签章属性对象PdfSignatureAppearance appearance = stamper.getSignatureAppearance();appearance.setReason(signatureInfo.getReason());appearance.setLocation(signatureInfo.getLocation());// 设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样 图片大小受表单域大小影响(过小导致压缩)// 签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角// 四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y//四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角yappearance.setVisibleSignature(new Rectangle(280, 220, 140, 600), 1, "sig1");// 读取图章图片Image image = Image.getInstance(signatureInfo.getImagePath());appearance.setSignatureGraphic(image);appearance.setCertificationLevel(signatureInfo.getCertificationLevel());// 设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)appearance.setRenderingMode(signatureInfo.getRenderingMode());// 这里的itext提供了2个用于签名的接口,可以自己实现,后边着重说这个实现// 摘要算法ExternalDigest digest = new BouncyCastleDigest();// 签名算法ExternalSignature signature = new PrivateKeySignature(signatureInfo.getPk(), signatureInfo.getDigestAlgorithm(),null);// 调用itext签名方法完成pdf签章 //数字签名格式,CMS,CADEMakeSignature.signDetached(appearance, digest, signature,signatureInfo.getChain(), null, null, null, 0,MakeSignature.CryptoStandard.CADES);inputStream = new ByteArrayInputStream(tempArrayOutputStream.toByteArray());// 定义输入流为生成的输出流内容,以完成多次签章的过程result = tempArrayOutputStream;outputStream = new FileOutputStream(new File(target));outputStream.write(result.toByteArray());outputStream.flush();} catch (Exception e) {e.printStackTrace();} finally {try {if (null != outputStream) {outputStream.close();}if (null != inputStream) {inputStream.close();}if (null != result) {result.close();}} catch (IOException e) {e.printStackTrace();}}}}

测试代码:

public static void main(String[] args) {try {ItextUtil app = new ItextUtil();// 将证书文件放入指定路径,并读取keystore ,获得私钥和证书链String pkPath = "src/main/resources/whj.p12";KeyStore ks = KeyStore.getInstance("PKCS12");ks.load(Files.newInputStream(Paths.get(pkPath)), PASSWORD);String alias = ks.aliases().nextElement();PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);// 得到证书链Certificate[] chain = ks.getCertificateChain(alias);//需要进行签章的pdfString path = "C:\\Users\\ASUS\\Desktop\\sq.pdf";// 封装签章信息SignatureInfo signInfo = new SignatureInfo();signInfo.setReason("牛逼");signInfo.setLocation("666");signInfo.setPk(pk);signInfo.setChain(chain);signInfo.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);signInfo.setDigestAlgorithm(DigestAlgorithms.SHA1);signInfo.setFieldName("demo");// 签章图片(网上生成的)signInfo.setImagePath("C:\\Users\\ASUS\\Desktop\\字节码\\学习测试30.png");signInfo.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);值越大,代表向x轴坐标平移 缩小 (反之,值越小,印章会放大)signInfo.setRectllx(100);值越大,代表向y轴坐标向上平移(大小不变)signInfo.setRectlly(200);// 值越大   代表向x轴坐标向右平移  (大小不变)signInfo.setRecturx(150);// 值越大,代表向y轴坐标向上平移(大小不变)signInfo.setRectury(150);//签章后的pdf路径app.sign(path, "C:\\Users\\ASUS\\Desktop\\字节码\\out.pdf", signInfo);} catch (Exception e) {e.printStackTrace();}}

实现对pdf 进行添加水印

一、添加水印工具类

public class WaterMark {/*** pdf生成水印** @param srcPdfPath       插入前的文件路径* @param tarPdfPath       插入后的文件路径* @param WaterMarkContent 水印文案* @param numberOfPage     每页需要插入的条数* @throws Exception*/public static void addWaterMark(String srcPdfPath, String tarPdfPath, String WaterMarkContent, int numberOfPage) throws Exception {PdfReader reader = new PdfReader(srcPdfPath);PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(tarPdfPath));PdfGState gs = new PdfGState();//设置字体BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);// 设置透明度gs.setFillOpacity(0.4f);int total = reader.getNumberOfPages() + 1;PdfContentByte content;for (int i = 1; i < total; i++) {content = stamper.getOverContent(i);content.beginText();content.setGState(gs);//水印颜色content.setColorFill(BaseColor.DARK_GRAY);//水印字体样式和大小content.setFontAndSize(font, 35);//插入水印  循环每页插入的条数for (int j = 0; j < numberOfPage; j++) {content.showTextAligned(Element.ALIGN_CENTER, WaterMarkContent, 300, 200 * (j + 1), 30);}content.endText();}stamper.close();reader.close();// 删除源文件,这个可以根据自己的需要来是否删除源文件boolean b = deleteFile(srcPdfPath);System.out.println("PDF水印添加完成!");}/**** 功能: 删除文件* @param path  需要删除的文件路径* @return {@link boolean}* @author luoheng*/public static boolean deleteFile(String path) {boolean result = false;File file = new File(path);if (file.isFile() && file.exists()) {int tryCount = 0;while (!result && tryCount++ < 10) {System.gc();result = file.delete();}}return result;}}

测试代码

我们传入需要加水印的pdf,设置对应的格式,数量,字体,以及对应输出的文件地址

public static void main(String[] args) {/*** pdf生成水印** @param srcPdfPath       需要加印的文件路径* @param tarPdfPath       加印后的文件输出路径* @param WaterMarkContent 水印文案* @param numberOfPage     每页需要插入的条数* @throws Exception*/String srcPdfPath = "C:\\Users\\ASUS\\Desktop\\字节码\\out.pdf";String tarPdfPath = "C:\\Users\\ASUS\\Desktop\\字节码\\out2.pdf";String WaterMarkContent = "程序员小王";Integer numberOfPage = 3;try {// 添加水印WaterMark.addWaterMark(srcPdfPath, tarPdfPath, WaterMarkContent, numberOfPage);} catch (Exception e) {e.printStackTrace();}}

效果图:

如果代码写的有问题,欢迎大家评论交流,进行指点!!!

也希望大家点个关注哦~~~~~~~~

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

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

相关文章

代码随想录——组合总数Ⅲ(Leetcode216)

题目链接 回溯 class Solution {List<List<Integer>> res new ArrayList<List<Integer>>();List<Integer> list new ArrayList<Integer>();public List<List<Integer>> combinationSum3(int k, int n) {backtracking(k, …

揭秘最强气象武器的库,SPEI-Python不可思议之处.

spei-python是一个专门用于计算标准化降水蒸散指数&#xff08;Standardized Precipitation Evapotranspiration Index,SPEI&#xff09;的Python库.SPEI是一种综合考虑降水和潜在蒸散发的干旱指数,用于评估干旱的严重程度和持续时间. 安装 ## 可以使用 pip 来安装 spei-pyth…

【EtherCAT电机板】CiA402增加cst模式

在EtherCAT电机板上实现cst功能&#xff0c;在xml中增加cst相关pdo&#xff0c;在402程序增加cst模式。 1、XML配置修改 cst模式需要用到目标转矩和反馈实际转矩PDO&#xff0c;结合CiA402手册&#xff0c;这两个PDO对应的索引号分别为&#xff1a;0x6071&#xff08;Target t…

基于微信小程序的在线答题小程序设计与实现

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

JavaFX VBox

VBox布局将子节点堆叠在垂直列中。新添加的子节点被放置在上一个子节点的下面。默认情况下&#xff0c;VBox尊重子节点的首选宽度和高度。 当父节点不可调整大小时&#xff0c;例如Group节点&#xff0c;最大垂直列的宽度基于具有最大优选宽度的节点。 默认情况下&#xff0c;…

分数布朗运动FBM期权定价模型

BS定价模型和蒙特卡洛模拟期权定价方法都 假设标的资产价格的对数服从布朗运动 &#xff0e; 但是实际 的金融市场中标的资产价格运动过程具有 “尖峰厚尾 ” 现象 &#xff0c; 运用分数布朗运动 &#xff08;FBM &#xff09;来刻画标的资产 价格的运动过程可能更加合适。 …

单列集合顶层接口Collection及五类遍历方式(迭代器)

collection add方法细节&#xff1a; remove方法细节&#xff1a; contains方法细节&#xff1a; 如果集合中存储的是自定义对象, student之类的, 也想通过contains进行判断, 就必须在javaBean中重写equals方法 contains在arrayList中源代码&#xff1a;在底层调用了equals方…

电路笔记 :LM3481MM/NOPB升压模块,升压电路原理

LM3481MM/NOPB LM3481MM/NOPB 是德州仪器&#xff08;Texas Instruments&#xff09;的一款广泛应用的DC-DC控制器&#xff0c;常用于电源管理应用&#xff0c;特别是在需要升压&#xff08;boost&#xff09;、反激&#xff08;flyback&#xff09;、SEPIC或反向配置的场合。…

python读取excel导入数据库

一、环境准备&#xff0c;安装包 pip install pandas openpyxl sqlalchemy二、数据准备 三、代码编写 from sqlalchemy import create_engine import pandas as pdclass GDPDataImporter:def __init__(self, db_type, dbapi, host, port, database, username, password):&quo…

【数据库编程-SQLite3(二)】API-增删改查基础函数-(含源码)

学习分享 1、sqlite3_exec函数1.1、使用sqlite3_exec进行【查】操作1.1.1、callback函数 1.2、使用sqlite3_exec进行【增、删、改】操作 2、sqlite3_get_table函数2.1、使用sqlite3_get_table函数进行【查】操作 1、sqlite3_exec函数 1.1、使用sqlite3_exec进行【查】操作 由于…

离散数学--连通性和矩阵

目录 0.关系的运算和性质 1.通路和回路 2.连通关系 3.割点&#xff08;边&#xff09;和点&#xff08;边&#xff09;割集 4.强&#xff08;弱&#xff09;连通&单向连通 0.关系的运算和性质 &#xff08;1&#xff09;这个运算包括了矩阵的运算&#xff0c;包括这个…

Mysql学习笔记-SQL优化总结

详细内容参见https://blog.csdn.net/qingwufeiyang_530/article/details/139705898?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22139705898%22%2C%22source%22%3A%22qingwufeiyang_530%22%7D

效果超越ControlNet+IP-Adapter和FreeControl!Ctrl-X:可控文生图新框架(加州大学英伟达)

文章链接&#xff1a;https://arxiv.org/pdf/2406.07540 项目链接&#xff1a;https://genforce.github.io/ctrl-x/ 最近的可控生成方法&#xff0c;如FreeControl和Diffusion Self-guidance&#xff0c;为文本到图像&#xff08;T2I&#xff09;扩散模型带来了细粒度的空间…

《全职猎人》

《全职猎人》 [1-2]是日本漫画家富坚义博的作品。 1999年版改编电视动画由日本动画公司负责动画制作&#xff0c;于1999年10月16日&#xff0d;2001年3月30日在富士电视台播出&#xff0c;该动画的故事至贪婪之岛篇章结束&#xff0c;全92话。 该作在富坚义博老师天马行空的想…

Gstreamer学习3----灌数据给管线之appsrc

参考资料 Basic tutorial 8: Short-cutting the pipeline gstreamer向appsrc发送帧画面的代码_gst appsrc可变帧率-CSDN博客 在官网教程Basic tutorial 8: Short-cutting the pipeline 里面&#xff0c;讲了一个例子&#xff0c;push音频数据给管线&#xff0c;视频的例子更…

二分+ST表+递推,Cf 1237D - Balanced Playlist

一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1237D - Codeforces 二、解题报告 1、思路分析 case3提示我们一件事情&#xff1a;如果存在某个位置永远不停止&#xff0c;那么所有位置都满足永远不停止 很容易证明 随着下标右移&#xff0c…

闲聊最近招聘面试

最近在为团队招聘开发人员&#xff0c;筛选了200多份简历&#xff0c;面试了50多人&#xff0c;感触良多&#xff0c;回想当初自己多多少少也存在这些问题&#xff0c;想着做一个总结。 首先&#xff0c;面试不是闲聊&#xff0c;要通过短暂的时间尽可能向面试官展示你的各方面…

Spring Boot + EasyExcel + SqlServer 进行批量处理数据

前言 在日常开发和工作中&#xff0c;我们可能要根据用户上传的文件做一系列的处理&#xff0c;本篇文章就以Excel表格文件为例&#xff0c;模拟用户上传Excel文件&#xff0c;讲述后端如何高效的进行数据的处理。 一.引入 EasyExcel 依赖 <!-- https://mvnrepository.com/…

VMware Ubuntu 虚拟机网卡消失及解决办法

VMware Ubuntu 虚拟机网卡消失 描述原因查找解决方法 描述 在正常使用过程中重启后发现 VMware Ubuntu 虚拟机中的网卡消失了&#xff0c;使用 ifconfig 查看只能看到本地回环&#xff1a; 原因查找 使用如下命令查看是否和我这边遇到的问题一致的原因。 sudo lshw -c netwo…

USB转I2C转SPI芯片CH341与CH347比较

1. 芯片中文资料&#xff1a; USB转I2C转SPI芯片CH341 高速USB转接芯片CH347转9M双串口转I2C转SPI转JTAG转SWD USB2.0高速转接芯片CH347应用开发手册 2. CH341与CH347比较&#xff1a; 类别CH341CH347备注串口速度2M9MCH347的串口速度更快设置CH341的I2C或SPI不能与串口同…