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

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

一、制作公章

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

然后对公章进行下载保存

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

盖章图片:
使用itextPDF实现PDF电子公章工具类

二、生成数字签名

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

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

  • keytool在jdk的bin目录下

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

2.2:启动黑窗命令

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

2.3:生成数字文件

D:keystoreserver.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:keystoreserver.keystore 

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

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

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

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

三、代码部分

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, '', null, true);             // 获取数字签章属性对象             PdfSignatureAppearance appearance = stamper                     .getSignatureAppearance();             appearance.setReason(signatureInfo.getReason());             appearance.setLocation(signatureInfo.getLocation());             // 设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样 图片大小受表单域大小影响(过小导致压缩)             // 签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角             // 四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y             //四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y             appearance.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,CADE             MakeSignature.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);             //需要进行签章的pdf              String 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();         }     } 

效果图:

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

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

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

发表评论

评论已关闭。

相关文章