使用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…

java框架技术xml文件存档

mybatis-config.xml <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><settin…

Qt 实战(4)信号与槽 | 4.3、信号连接信号

文章目录 一、信号连接信号1、什么是信号连接信号&#xff1f;2、如何实现信号连接信号3、总结 前言&#xff1a; 在Qt框架中&#xff0c;信号与槽&#xff08;Signals and Slots&#xff09;机制是对象间通信的核心。通常情况下&#xff0c;我们习惯于将信号连接到槽函数上&am…

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

个人介绍 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;…

Linux sftp服务搭建,新增账户

注意&#xff1a;操作前记得多开一个窗口用top挂起&#xff0c;修改失败可能会导致ssh再也连接不上! 1、创建用户&#xff0c;并且不允许登录 #创建用户&#xff0c;并且不允许登录 useradd -s /sbin/nologin pppsftp#设置密码 passwd pppsftp#设置用户不过期 chage -M -1 p…

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

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

鸿蒙开发电话服务:【@ohos.telephony.radio (网络搜索)】

网络搜索 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import radio from ohos.telephony.radioradio.getRadioTech getRadioTech(slotId: number, callback: AsyncCallback<{p…

【51单片机】从零学郭天祥10天入门学会51单片机

本文用于个人笔记。 一、单片机预备知识 1.1 电平特性 数字电路只有两种电平&#xff1a;高和低&#xff08;本课程中&#xff09;定义单片机为TTL电平 高&#xff1a;5V 低&#xff1a;0V RS232电平&#xff1a;计算机的串口 高&#xff1a;-12V …

单列集合顶层接口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或反向配置的场合。…

spring注解

PreAuthorize springsecurity中注解 package org.springframework.security.access.prepost; /** * PreAuthorize注解用于定义方法或类型&#xff08;类或接口&#xff09;的访问权限。它支持使用Spring表达式语言&#xff08;SpEL&#xff09; * 来指定执行注解方法或访问注…

一、从C语言到C++(一)

一、从C语言到C&#xff08;一&#xff09; C介绍C语言和C的联系C介绍 头文件命名空间定义命名空间使用命名空间中的名称使用using声明或指令命名空间与C语言的对比给命名空间起别名注意事项std 标准输入输出std::endl使用std::cout进行输出使用std::cin进行输入格式化输出 C介…

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进行【查】操作 由于…

计算机行业

计算机行业环境分析 2022.01.12 计算机行业环境分析 计算机专业就业前景 随着科技的进步和信息事业的发展&#xff0c;尤其是计算机技术的发展与网络应用的逐渐普及。计算机已成为人们工作和生活中不可缺少的东西。IT行业迅猛发展&#xff0c;就业工作岗位也比比皆是。在最近…

Web前端align的奥秘:深入剖析与实战应用

Web前端align的奥秘&#xff1a;深入剖析与实战应用 在Web前端开发中&#xff0c;align属性似乎是一个简单却充满奥秘的存在。它涉及到文本、图片、表格等多种元素的对齐方式&#xff0c;是网页布局中不可或缺的一环。然而&#xff0c;随着CSS的不断发展&#xff0c;align属性…

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

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