java PDF盖章-位置定位,请看这篇文章。

本文为关键词盖章,需求就是根据关键词在pdf进行签章,如:pdf尾页盖上xxx机构的电子章。

直接上代码:所需要的依赖和位置定位的差不多,请看上文。

Itext5PdfSign.java

package test02itextpdf.keyword;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 lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.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);String alias = ks.aliases().nextElement();PrivateKey privateKey = (PrivateKey) ks.getKey(alias, password.toCharArray());signConfig.setChain(ks.getCertificateChain(alias));signConfig.setPrivateKey(privateKey);}signConfig.setDigest(new BouncyCastleDigest());signConfig.setSignature(new PrivateKeySignature(signConfig.getPrivateKey(), DigestAlgorithms.SHA256, BouncyCastleProvider.PROVIDER_NAME));if (Objects.isNull(signConfig.getChapterImg())) {signConfig.setChapterImg(Image.getInstance(signConfig.getChapterImgPath()));}Image chapterImg = signConfig.getChapterImg();signConfig.setStampWidth(chapterImg.getWidth());signConfig.setStampHeight(chapterImg.getHeight());this.signConfig = signConfig;} catch (Exception e) {throw new RuntimeException("init error", e);}}private void checkInit(SignConfig signConfig) {if (StringUtils.isEmpty(signConfig.getSignP12Path())) {throw new RuntimeException("缺少签章用的公私钥对信息");}if (StringUtils.isNotEmpty(signConfig.getSignP12Path()) && StringUtils.isEmpty(signConfig.getSignP12Password())) {throw new RuntimeException("签章证书密码配置缺少");}if (Objects.isNull(signConfig.getChapterImg()) && StringUtils.isEmpty(signConfig.getChapterImgPath())) {throw new RuntimeException("缺少签章图片地址信息");}if (StringUtils.isEmpty(signConfig.getSignername())) {throw new RuntimeException("缺少签章者名称信息");}if (StringUtils.isEmpty(signConfig.getReason())) {throw new RuntimeException("缺少签章原因信息");}if (StringUtils.isEmpty(signConfig.getLocation())) {throw new RuntimeException("缺少签章位置信息");}if (StringUtils.isEmpty(signConfig.getSignFiledName())) {throw new RuntimeException("缺少签章域名称信息");}if (Objects.nonNull(signConfig.getTsaClientFactory())) {signConfig.setNoTsa(false);}if (Objects.nonNull(signConfig.getTsaUrl())) {signConfig.setNoTsa(false);signConfig.tsaClientFactory = new TsaClientBCFactory(signConfig.getTsaUrl());}}private TSAClient getTsaClient() {if (signConfig.isNoTsa()) {return null;}return signConfig.tsaClientFactory.newTSAClient();}@Datapublic static class SignConfig {/*** 签章hash 及签名实现*/private ExternalDigest digest;private ExternalSignature signature;/*** 证书链及私钥*/private Certificate[] chain;private PrivateKey privateKey;/*** 签章原因*/private String reason;/*** 签章位置*/private String location;/*** 签章者名称*/private String signername;/*** 签章图片地址*/private Image chapterImg;private String chapterImgPath;/*** 签章域名称可根据域查找章的位置*/private String signFiledName;/*** 签章公私钥文件*/private String signP12Path;private String signP12Password;/*** 签章关键词及关键词所在的页码*/private String signKeyWord;private Integer signKeyWordPageNum;/*** 签章图片的宽高*/private float stampHeight;private float stampWidth;/*** 签章时间服务*/private boolean noTsa = true;private TsaClientFactory tsaClientFactory;private String tsaUrl;}private PdfLocationResult calcSignLocation(PdfReader reader, KeyWordFinder.KeyWordMatchType matchType) {/*** 1. 如果关键字存在,则签章在关键字上* 2. 如果关键字不存在 则签章在尾页的右下角*/KeyWordLocation keyWordLocation = keyWordLocation(reader, signConfig.getSignKeyWord(), signConfig.getSignKeyWordPageNum(), matchType);if (Objects.nonNull(keyWordLocation)) {/*** 计算规则:* 1. 由于获取的关键词文件块宽高过于夸张,所以先计算关键词文本块矩形右下角坐标( keyWordLocation.getUrx(),keyWordLocation.getUry()-文本块高度)* 2. 然后将 文本块右下角坐标作为签章矩形的中心点,然后计算签章域的左下角右上角坐标* 3.签章域超出pdf页宽高,并做溢出处理*/float keyWordTextBlockHeight = keyWordLocation.getKeyWordTextBlockHeight();/*** 关键字右下角坐标*/float keyWordLrx = keyWordLocation.getUrx();float keyWordLry = keyWordLocation.getUry() - keyWordTextBlockHeight;//签章域左下角坐标float llx = keyWordLrx - signConfig.getStampWidth() / 2;float lly = keyWordLry - signConfig.getStampHeight() / 2;/*** 横纵坐标向溢出处理*/Rectangle pageSize = reader.getPageSize(keyWordLocation.getPageNum());if (llx + signConfig.getStampWidth() > pageSize.getWidth()) {llx = pageSize.getWidth() - signConfig.getStampWidth();}if (lly < 0) {llx = 0;}//签章域右上角坐标float urx = llx + signConfig.getStampWidth();float ury = lly + signConfig.getStampHeight();Rectangle rectangle = new Rectangle(llx, lly, urx, ury);LOG.debug("查找到关键词[{}]位置,坐标为{}", keyWordLocation.getText(), keyWordLocation);return new PdfLocationResult(keyWordLocation.getPageNum(), rectangle);} else {int numberOfPages = reader.getNumberOfPages();Rectangle lastPageSize = reader.getPageSize(numberOfPages);float pageWidth = lastPageSize.getWidth();//左下角坐标 lly 表示距离底部的距离float llx = pageWidth - signConfig.getStampWidth();float lly = 50;//右上角坐标float urx = llx + signConfig.getStampWidth();float ury = lly + signConfig.getStampHeight();Rectangle rectangle = new Rectangle(llx, lly, urx, ury);LOG.debug("未查找到关键词位置,签章位置默认在尾页", signConfig.getSignKeyWord());return new PdfLocationResult(numberOfPages, rectangle);}}/*** 根据关键词 计算签章位置** @param pdfReader      解析reader* @param keyWord        关键词* @param keyWordPageNum 关键词所在页码* @return*/private KeyWordLocation keyWordLocation(PdfReader pdfReader, String keyWord, Integer keyWordPageNum, KeyWordFinder.KeyWordMatchType matchType) {List<KeyWordLocation> keyWordLocationList = new ArrayList<>();try {int pageSize = pdfReader.getNumberOfPages();PdfReaderContentParser pdfReaderContentParser = new PdfReaderContentParser(pdfReader);IntStream pageStream = null;if (Objects.nonNull(keyWordPageNum)) {pageStream = IntStream.of(keyWordPageNum);} else {pageStream = IntStream.range(1, pageSize + 1);//含头不含尾}pageStream.forEach(pageNum -> {try {pdfReaderContentParser.processContent(pageNum, new KeyWordFinder(keyWord, pageNum, keyWordLocationList));} catch (IOException e) {throw new RuntimeException(e);}});} catch (Exception e) {throw new RuntimeException(e);}KeyWordLocation keyWordLocation = null;if (keyWordLocationList.isEmpty()) {return null;}if (keyWordLocationList.size() == 1) {keyWordLocation = keyWordLocationList.get(0);} else {switch (matchType) {case MATCH_LAST:keyWordLocation = LittlePdfUtil.getLast(keyWordLocationList);break;case MATCH_FIRST:keyWordLocation = keyWordLocationList.get(0);break;default:keyWordLocation = LittlePdfUtil.getLast(keyWordLocationList);break;}}if (KeyWordFinder.KEYWORD_MATCH_TYPE_FULL.equals(keyWordLocation.getKeywordMatchType())) {return keyWordLocation;} else if (KeyWordFinder.KEYWORD_MATCH_TYPE_MIX.equals(keyWordLocation.getKeywordMatchType()) &&Objects.nonNull(keyWordLocation.getMixMatchCharList())) {/*** 如果关键词被分拆,则返回中间字符的坐标*/List<KeyWordCharLocation> mixMatchCharList = keyWordLocation.getMixMatchCharList();KeyWordLocation midChar = KeyWordFinder.getMidChar(keyWord, mixMatchCharList);keyWordLocation.setLlx(midChar.getLlx());keyWordLocation.setLly(midChar.getLly());keyWordLocation.setUrx(midChar.getUrx());keyWordLocation.setUry(midChar.getUry());keyWordLocation.setKeyWordTextBlockHeight(midChar.getKeyWordTextBlockHeight());keyWordLocation.setKeyWordTextBlockWidth(midChar.getKeyWordTextBlockWidth());return keyWordLocation;}return keyWordLocation;}public static class KeyWordFinder extends TextMarginFinder {@Getter@Setterprivate String keyWord;@Getter@Setterprivate Integer pageNum;@Getter@Setterprivate List<KeyWordLocation> keyWordLocationList;/*** 匹配类型* <p>* KEYWORD_MATCH_TYPE_FULL 关键词完全匹配* KEYWORD_MATCH_TYPE_MIX 关键词混乱匹配*/public static final Integer KEYWORD_MATCH_TYPE_FULL = 1,KEYWORD_MATCH_TYPE_MIX = 2;/*** 当前模式 是否为混乱模式*/private boolean isMixMatch;/*** 混乱匹配模式,已匹配的字符数(左匹配)*/private Integer keyWordMixMatchCharMatchCount = 0;public KeyWordFinder(String keyWord, Integer pageNum, List<KeyWordLocation> keyWordLocationList) {this.keyWord = keyWord;this.pageNum = pageNum;this.keyWordLocationList = keyWordLocationList;}@Overridepublic void renderText(TextRenderInfo renderInfo) {super.renderText(renderInfo);String text = renderInfo.getText();LOG.debug("pdf文本:[{}] 文本宽度{},文本高度", text, this.getWidth(), this.getHeight());//查找到关键词,并设置关键词位置if (LittlePdfUtil.isNotEmpty(text)) {if (text.contains(keyWord)) {keyWordLocationList.add(toKeyWordLocation(text, KEYWORD_MATCH_TYPE_FULL));return;} else {handleMatchMix(text);return;}}}private void handleMatchMix(String text) {if (!isMixMatch) {int matchCount = leftMatch(keyWord, text, 0);if (matchCount > 0) {isMixMatch = true;keyWordMixMatchCharMatchCount = matchCount;KeyWordLocation keyWordMixMatchLocation = toKeyWordLocation(text, KEYWORD_MATCH_TYPE_MIX);KeyWordCharLocation keyWordCharLocation = toKeyWordCharLocation(text);keyWordCharLocation.setMixMatchCount(matchCount);keyWordCharLocation.setMixMatchStart(0);List<KeyWordCharLocation> mixMatchCharList = new ArrayList<>();mixMatchCharList.add(keyWordCharLocation);keyWordMixMatchLocation.setMixMatchCharList(mixMatchCharList);keyWordLocationList.add(keyWordMixMatchLocation);return;}}if (isMixMatch) {int matchCount = leftMatch(keyWord, text, keyWordMixMatchCharMatchCount);if (keyWordMixMatchCharMatchCount.equals(keyWord.length())) {//匹配结束isMixMatch = false;keyWordMixMatchCharMatchCount = 0;} else if (matchCount > 0) {//继续匹配中List<KeyWordCharLocation> mixMatchCharList = LittlePdfUtil.getLast(keyWordLocationList).getMixMatchCharList();KeyWordCharLocation keyWordCharLocation = toKeyWordCharLocation(text);keyWordCharLocation.setMixMatchCount(matchCount);keyWordCharLocation.setMixMatchStart(keyWordMixMatchCharMatchCount);mixMatchCharList.add(keyWordCharLocation);keyWordMixMatchCharMatchCount += matchCount;} else {isMixMatch = false;keyWordMixMatchCharMatchCount = 0;//删除不完全匹配LittlePdfUtil.removeLastList(keyWordLocationList, 1);}}}private static int leftMatch(String keyWord, String text, int pos) {int matchCount = 0, keyWordLen = keyWord.length();for (int i = 0, len = text.length(); i < len; i++) {int matchStart = pos + matchCount;if (matchStart >= keyWordLen) {break;}if (Objects.equals(keyWord.charAt(matchStart), text.charAt(i))) {matchCount++;}}if (matchCount > 0) {return matchCount;}return -1;}public static enum KeyWordMatchType {MATCH_LAST,MATCH_FIRST;}private KeyWordLocation toKeyWordLocation(String text, Integer keywordMatchType) {KeyWordLocation keyWordLocation = new KeyWordLocation();keyWordLocation.setKeyWordTextBlockHeight(this.getHeight());keyWordLocation.setKeyWordTextBlockWidth(this.getWidth());keyWordLocation.setLlx(this.getLlx());keyWordLocation.setLly(this.getLly());keyWordLocation.setUrx(this.getUrx());keyWordLocation.setUry(this.getUry());keyWordLocation.setText(text);keyWordLocation.setPageNum(pageNum);keyWordLocation.setKeywordMatchType(keywordMatchType);return keyWordLocation;}private KeyWordCharLocation toKeyWordCharLocation(String text) {KeyWordCharLocation keyWordCharLocation = new KeyWordCharLocation();keyWordCharLocation.setKeyWordTextBlockHeight(this.getHeight());keyWordCharLocation.setKeyWordTextBlockWidth(this.getWidth());keyWordCharLocation.setLlx(this.getLlx());keyWordCharLocation.setLly(this.getLly());keyWordCharLocation.setUrx(this.getUrx());keyWordCharLocation.setUry(this.getUry());keyWordCharLocation.setText(text);keyWordCharLocation.setPageNum(pageNum);keyWordCharLocation.setKeywordMatchType(KEYWORD_MATCH_TYPE_MIX);return keyWordCharLocation;}public static KeyWordCharLocation getMidChar(String keyWord, List<KeyWordCharLocation> mixMatchCharList) {int midIndex = keyWord.length() / 2, count = 0;for (int i = 0, len = mixMatchCharList.size(); i < len; i++) {KeyWordCharLocation keyWordCharLocation = mixMatchCharList.get(i);count += keyWordCharLocation.getMixMatchCount();if (count >= midIndex) {return keyWordCharLocation;}}return mixMatchCharList.get(0);}}/*** 签章关键词文本位置*/@Datapublic static class KeyWordLocation {/*** 文本*/private String text;/*** 关键词所在pdf页码*/private Integer pageNum;/*** 文本块所在矩形左下角坐标*/private float llx;private float lly;/*** 文本块所在矩形右上角角坐标*/private float urx;private float ury;/*** 文本块宽高*/private float keyWordTextBlockWidth;private float keyWordTextBlockHeight;/*** 关键词匹配类型 参见keyFinder*/private Integer keywordMatchType;/*** 关键词被解析成多个TextRenderInfo*/private List<KeyWordCharLocation> mixMatchCharList;}/*** 混乱匹配模式下的 打散的关键词字符位置*/@Datapublic static class KeyWordCharLocation extends KeyWordLocation {/*** 混乱匹配时的起始位置*/private Integer mixMatchStart;/*** 匹配的字符数*/private Integer mixMatchCount;}@Datapublic static class PdfLocationResult {/*** 签章所在pdf页码*/private int pageNum;/*** 签章矩形*/private Rectangle rectangle;public PdfLocationResult(int pageNum, Rectangle rectangle) {this.pageNum = pageNum;this.rectangle = rectangle;}}
}

LittlePdfUtil.java

package test02itextpdf.keyword;import org.apache.commons.io.IOUtils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;public class LittlePdfUtil {public static String streamToString(InputStream inputStream, String encoding) throws IOException {return IOUtils.toString(inputStream, encoding);}public static boolean isEmpty(String str) {return str == null || str.length() == 0;}public static boolean isNotEmpty(String str) {return str != null && str.length() >= 0;}public static byte[] streamToBytes(InputStream inputStream) throws IOException {ByteArrayOutputStream outputStream = new ByteArrayOutputStream();byte[] buf = new byte[4 << 1024];int len = -1;while ((len = inputStream.read(buf)) != -1) {outputStream.write(buf, 0, len);}inputStream.close();return outputStream.toByteArray();}public static void removeLastList(List list, Integer num) {for (int i = 0; i < num; i++) {if (!list.isEmpty()) {list.remove(list.size() - 1);}}}public static <T> T getLast(List<T> list) {return list.get(list.size() - 1);}public static void main(String[] args) {System.out.println("123".substring(0, 3));}}

RSAUtil.java

package test02itextpdf.keyword;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;public final class RSAUtil {private static final Logger LOG = LoggerFactory.getLogger(RSAUtil.class);public static final String KEYSTORE_TYPE_P12 = "PKCS12";public static final String KEYSTORE_TYPE_JKS = "JKS";public static KeyStore getKeyStore(String filePath, String keyPassword) throws Exception {KeyStore keyStore = KeyStore.getInstance(guessKeyStoreType(filePath));FileInputStream file = new FileInputStream(new File(filePath));keyStore.load(file, keyPassword.toCharArray());return keyStore;}public static KeyStore getKeyStore(InputStream inputStream, String keyPassword) throws Exception {KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE_P12);keyStore.load(inputStream, keyPassword.toCharArray());return keyStore;}public static String guessKeyStoreType(String filePath) {String ext = filePath.substring(filePath.lastIndexOf(".")+1);if (ext.equals("p12") || ext.equals("pfx")) {return KEYSTORE_TYPE_P12;}if (ext.equals("jks")) {return KEYSTORE_TYPE_JKS;}return null;}}

TsaClientBCFactory.java

package test02itextpdf.keyword;import com.itextpdf.text.pdf.security.TSAClient;
import com.itextpdf.text.pdf.security.TSAClientBouncyCastle;public class TsaClientBCFactory implements TsaClientFactory {private String tsaUrl;public TsaClientBCFactory(String tsaUrl) {this.tsaUrl = tsaUrl;}@Overridepublic TSAClient newTSAClient() {return new TSAClientBouncyCastle(tsaUrl);}
}

TsaClientFactory.java

package test02itextpdf.keyword;import com.itextpdf.text.pdf.security.TSAClient;public interface TsaClientFactory {TSAClient newTSAClient();
}

PdfTest.java(测试)

package test02itextpdf.keyword;
import org.junit.Before;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.springframework.util.StopWatch;public class PdfTest {private Itext5PdfSign itext5PdfSign;@Testpublic void signTest() throws Exception {StopWatch stopWatch = new StopWatch();stopWatch.start("signBig");itext5PdfSign.sign(new FileInputStream("E:\\iotest\\itextpdf\\keyword\\anxin2.pdf"), new FileOutputStream("E:\\iotest\\itextpdf\\keyword\\anxin2_sign.pdf"));stopWatch.stop();System.out.println(stopWatch.prettyPrint());}@Beforepublic void before() {String signername = "安心集团有限公司";String reason = "官方承认,不可篡改";String location = "安心集团有限公司";String password = "123456";String p12Path = "E:\\iotest\\itextpdf\\keyword\\test2.p12";String chapterPath = "E:\\iotest\\itextpdf\\keyword\\anxinseal.png";String field_name = "sign_Field";Itext5PdfSign.SignConfig signConfig = new Itext5PdfSign.SignConfig();signConfig.setSignP12Path(p12Path);signConfig.setSignP12Password(password);signConfig.setChapterImgPath(chapterPath);signConfig.setSignername(signername);signConfig.setReason(reason);signConfig.setLocation(location);signConfig.setSignFiledName(field_name);signConfig.setSignKeyWord("安心集团有限公司");itext5PdfSign = new Itext5PdfSign(signConfig);}
}

全部代码结构:

效果展示:(目前不清楚为啥不盖在关键词上面,等有时间再看看代码)

 注意点:

pdf文本查找时,一个关键词可能被拆分成多个区块,所以要进行特殊处理

itext pdf坐标系

page页的左下角为坐标原点,定位一个矩形坐标时,根据左下角和右上角两个点坐标即可确定一个矩形的位置。

原文链接:https://blog.csdn.net/do_bset_yourself/article/details/109150218?spm=1001.2014.3001.5501

java为PDF盖(签)电子签章--关键词定位相关推荐

  1. java为PDF盖(签)电子签章--位置定位

    1.电子签章简介 电子签章,与我们所使用的数字证书一样,是用来做为身份验证的一种手段,泛指所有以电子形式存在,依附在电子文件并与其逻辑关联,可用以辨识电子文件签署者身份,保证文件的完整性,并表示签署者 ...

  2. 如何用 Java 对 PDF 文件进行电子签章

    转自:如何用 Java 对 PDF 文件进行电子签章 - Ferocious - 博客园 一.概述 二.技术选型 三.生成一个图片签章 四.如何按模板生成PDF文件 五.如何生成PKSC12证书 六. ...

  3. 如何用 Java 对 PDF 文件进行电子签章(六)如何进行多次PDF签名 及总结

    参考: https://blog.csdn.net/javasun608/article/details/79307845 如何进行多次PDF签名   生成多个签章重点代码,已在SignPdf.jav ...

  4. 如何用 Java 对 PDF 文件进行电子签章(五) 如何生成一个高清晰的签章

    参考: https://blog.csdn.net/javasun608/article/details/79307845    具体步骤: 由PDF模板生成一个PDF文件.加签章.由itext5 生 ...

  5. 如何用 Java 对 PDF 文件进行电子签章(二)生成一个图片签章

    参考: https://blog.csdn.net/javasun608/article/details/79307845 https://blog.csdn.net/zdavb/article/de ...

  6. Java 对 PDF 文件进行电子签章 如何生成PKCS12证书

    记录世界,记住你.侵权请联系博主删除. 转自:https://blog.csdn.net/qq_30336433/article/details/83819572 pom.xml <depend ...

  7. pdf 电子签章 java_在pdf上加盖电子签章

    在pdf上加盖电子签章,并不是只是加个印章图片,.而是要使用一对密钥中的私钥对文件进行签字.为啥要用私钥呢?很简单,因为公钥是公开的,其他人才可以用公钥为你证明,这个文件是你签的.这就是我们常说的:私 ...

  8. 君子签电子签章助推企业实现印章“集中统一管控”和“分级分权管理”

    对于中大型企业来说,印章管理一直以来都是个"老大难"问题. 在中大型企业,印章数量多,大多分散在各个分/子公司的各个部门,企业印章无法统一进行有效管理.印章分散各地,异地分/子公司 ...

  9. 90%的合同麻烦都源于签约“漏洞”,君子签电子签章闭坑指南来了!

    业务签约中,有哪些合同麻烦呢?文字套路.印章造假.假冒代签.乱签漏签.信息泄露-事实上,这些签约"漏洞"都是源于签约风险排查不到位,管控不力而导致的,以至于后期履约中纠纷也不断. ...

最新文章

  1. vue入门实践,style和数据绑定
  2. UML第一次作业:UML用例图绘制
  3. 开关电源雷击浪涌整改_大佬多年经验总结,开关电源EMI整改策略
  4. 在Linux(ubuntu server)上面安装NodeJS的正确方法
  5. OpenCASCADE:构建线程
  6. Zookeeper 的 ZAB 协议
  7. 模型如何京东培训6万人
  8. iPhone 12 Pro最新概念图:五摄相机模组也带下巴
  9. 中文文本对齐_word排版技巧:如何让词组文字分散对齐
  10. java 线程池 连接池_浅析Tomcat高并发之连接池、线程池
  11. 力软敏捷开发框架工作流实现技术
  12. 【图像融合】基于matlab小波变换图像融合【含Matlab源码 392期】
  13. 投入产出表matlab,投入产出分析投入产出表.doc
  14. java实现条形图_java – 使用Apache POI在Excel中创建条形图
  15. SRAM SROM DRAM DROM DDR NAND FLASH EMMC的区别
  16. 【高德地图API】从头德国高中生JS API(三)覆盖物——大喊|折线|多边形|信息表|聚合marker|点蚀图|照片覆盖...
  17. AI Earth ——开发者模式案例8:利用Landsat-8数据进行地表温度反演
  18. scratch简单编程
  19. 网站关键词优化--如何优化6目标关键词
  20. 逻辑回归原理及spark例子

热门文章

  1. 【单片机笔记】使用ESP8266的WIFI-MQTT串口透传模块实现TLINK平台测试
  2. 计算机科学世界排名前5的著名错误
  3. 国泰君安基于OpenStack构建金融云
  4. VMware 15Pro安装ubuntu 18.04
  5. JavaScript基础应用(动态生成可变柱状图)
  6. YDOOK:Pytorch教程:tensor 张量内各个元素之和 相加值输出
  7. JQuery plugs Question
  8. 第四章 决策树和ID3 python3.5.1代码理解
  9. 对日面试的42个问题,你会吗?
  10. redis-JedisPoolConfig配置