pdf操作之根据关键词签章

本文介绍了一种使用Java和iText库根据关键词在PDF文件中自动签章的方法。该方法能够定位到关键词出现的位置,并在此基础上放置电子签章。

pdf操作之根据关键词签章

之前写过一篇pdf签章的文章 java操作pdf制作电子签章, 发现有博友反馈需求根据关键词进行签章,之前的想法时由前端配合,指定pdf位置,java代码执行签名操作,正好最近也有个类似的需求,索性就填下之前的坑吧

需求描述

根据关键词在pdf进行签章,如 pdf尾页盖上xxx机构的电子章
直接上干货

代码实现

package com.taoyuanx.littlepdf.sign;

import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfSignatureAppearance;
import com.itextpdf.text.pdf.PdfSignatureAppearance.RenderingMode;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfStream;
import com.itextpdf.text.pdf.parser.PdfReaderContentParser;
import com.itextpdf.text.pdf.parser.TextMarginFinder;
import com.itextpdf.text.pdf.parser.TextRenderInfo;
import com.itextpdf.text.pdf.security.*;
import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;
import com.taoyuanx.littlepdf.utils.LittlePdfUtil;
import com.taoyuanx.littlepdf.utils.RSAUtil;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;

/**
 * pdf 签章实现类
 */
public class Itext5PdfSign {
    private static final Logger LOG = LoggerFactory.getLogger(Itext5PdfSign.class);

    private SignConfig signConfig;

    public void sign(InputStream waitSignPdf, OutputStream signedPdf) {
        try {
            PdfReader reader = new PdfReader(waitSignPdf);
            /**
             * false的话,pdf文件只允许被签名一次,多次签名,最后一次有效
             * true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改
             */
            PdfStamper stamper = PdfStamper.createSignature(reader, signedPdf, '\0', null, true);
            /**
             * 设定签章为高清章,默认模糊
             */
            stamper.getWriter().setCompressionLevel(PdfStream.BEST_COMPRESSION);
            /**
             * 设定签章属性
             */
            PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
            appearance.setReason(signConfig.getReason());
            appearance.setLocation(signConfig.getLocation());
            appearance.setSignatureCreator(signConfig.getSignername());
            PdfLocationResult locationResult = calcSignLocation(reader, KeyWordFinder.KeyWordMatchType.MATCH_LAST);
            appearance.setVisibleSignature(locationResult.getRectangle(), locationResult.getPageNum(), signConfig.getSignFiledName());
            /**
             * 设定签章图片,签章类别
             */
            appearance.setSignatureGraphic(signConfig.getChapterImg());
            //NOT_CERTIFIED 不会导致pdf上其他签章无效
            appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);
            /**
             * 设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)
             */
            appearance.setRenderingMode(RenderingMode.GRAPHIC);
            /**
             * 指定摘要算法
             */
            ExternalDigest digest = signConfig.getDigest();
            /**
             * 指定签名对象
             */
            ExternalSignature signature = signConfig.getSignature();
            /**
             * 构造时间时间戳服务器
             */
            TSAClient tsaClient = getTsaClient();
            /**
             * itext 签章
             */
            MakeSignature.signDetached(appearance, digest, signature, signConfig.getChain(), null, null, tsaClient, 0, CryptoStandard.CMS);
        } catch (Exception e) {
            throw new RuntimeException("签章异常", e);
        }
    }


    public Itext5PdfSign(SignConfig signConfig) {
        checkInit(signConfig);
        try {
            BouncyCastleProvider bc = new BouncyCastleProvider();
            Security.addProvider(bc);
            if (StringUtils.isNotEmpty(signConfig.getSignP12Path())) {
                String p12Path = signConfig.getSignP12Path();
                String password = signConfig.getSignP12Password();
                KeyStore ks = RSAUtil.getKeyStore(p12Path, password);
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值