参考:

  1. https://blog.csdn.net/javasun608/article/details/79307845

  
具体步骤: 由PDF模板生成一个PDF文件、加签章。由itext5 生成的签章 图片更加清晰

1. 由PDF模板生成一个PDF文件,见代码注解

    import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import com.itextpdf.text.DocumentException;import com.itextpdf.text.pdf.AcroFields;import com.itextpdf.text.pdf.AcroFields.Item;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.text.pdf.PdfReader;import com.itextpdf.text.pdf.PdfStamper;public class PDFUtils {/*** @param fields* @param data* @throws IOException* @throws DocumentException*/private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {List<String> keys = new ArrayList<String>();Map<String, Item> formFields = fields.getFields();for (String key : data.keySet()) {if(formFields.containsKey(key)){String value = data.get(key);fields.setField(key, value); // 为字段赋值,注意字段名称是区分大小写的keys.add(key);}}Iterator<String> itemsKey = formFields.keySet().iterator();while(itemsKey.hasNext()){String itemKey = itemsKey.next();if(!keys.contains(itemKey)){fields.setField(itemKey, " ");}}}/*** @param templatePdfPath*            模板pdf路径* @param generatePdfPath*            生成pdf路径* @param data*            数据*/public static String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {OutputStream fos = null;ByteArrayOutputStream bos = null;PdfReader reader=null;PdfStamper ps =null;try {reader = new PdfReader(templatePdfPath);bos = new ByteArrayOutputStream();/* 将要生成的目标PDF文件名称 */ps = new PdfStamper(reader, bos);/* 使用中文字体 */BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();fontList.add(bf);/* 取出报表模板中的所有字段 */AcroFields fields = ps.getAcroFields();fields.setSubstitutionFonts(fontList);fillData(fields, data);/* 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true*/ps.setFormFlattening(true);ps.close();fos = new FileOutputStream(generatePdfPath);fos.write(bos.toByteArray());fos.flush();return generatePdfPath;} catch (Exception e) {e.printStackTrace();} finally {if (fos != null) {try {fos.close();} catch (IOException e) {e.printStackTrace();}}if (bos != null) {try {bos.close();} catch (IOException e) {e.printStackTrace();}}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}if (ps != null) {try {ps.close();} catch (IOException e) {e.printStackTrace();}}return null;}public static void main(String[] args) {Map<String, String> data = new HashMap<String, String>();//key为pdf模板的form表单的名字,value为需要填充的值data.put("title", "在线医院");data.put("case", "123456789");data.put("date", "2018.12.07");data.put("name", "gitbook");data.put("sex", "男");data.put("age", "29");data.put("phone", "13711645814");data.put("office", "内科");data.put("cert", "身痒找打");data.put("drug", "1、奥美拉唑肠溶胶囊             0.25g10粒×2板 ");data.put("dose", "×2盒");data.put("cons", "用法用量:口服 一日两次 一次2粒");data.put("tips", "温馨提示");data.put("desc", "尽量呆在通风较好的地方,保持空气流通,有利于病情康复。尽量呆在通风较好的地方");generatePDF("C:\\Users\\zhilin\\Desktop\\chat\\tpl.pdf", "C:\\Users\\zhilin\\Desktop\\chat\\filled.pdf", data );}}

参考原作者图片就好

2. 对PDF文件进行签章

   经过上面的代码可以生成一个名为sign.jpg的签章图片,生成一个keystore.p12的证书文件,还有一个已经通过模板填充了表单的名为filled.pdf的pdf文件。下面就可通过以上材料生成一个签名的PDF文件。

    import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.security.KeyStore;import java.security.PrivateKey;import java.security.Security;import java.security.cert.Certificate;import java.util.UUID;import org.bouncycastle.jce.provider.BouncyCastleProvider;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.security.BouncyCastleDigest;import com.itextpdf.text.pdf.security.DigestAlgorithms;import com.itextpdf.text.pdf.security.ExternalDigest;import com.itextpdf.text.pdf.security.ExternalSignature;import com.itextpdf.text.pdf.security.MakeSignature;import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;import com.itextpdf.text.pdf.security.PrivateKeySignature;public class SignPdf {/*** @param password 秘钥密码 * @param keyStorePath   秘钥文件路径 * @param signPdfSrc   签名的PDF文件* @param signImage     签名图片文件* @param x    x坐标* @param y    y坐标* @return*/public static byte[] sign(String password, String keyStorePath, String signPdfSrc, String signImage,   float x, float y) {File signPdfSrcFile = new File(signPdfSrc);PdfReader reader = null;ByteArrayOutputStream signPDFData = null;PdfStamper stp = null;FileInputStream fos = null;try {//  加入算法提供者BouncyCastleProvider provider = new BouncyCastleProvider();Security.addProvider(provider);KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());fos = new FileInputStream(keyStorePath);// 私钥密码 为Pkcs生成证书是的私钥密码 123456ks.load(fos, password.toCharArray()); String alias = (String) ks.aliases().nextElement();// 获取私钥PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());// 获取证书链Certificate[] chain = ks.getCertificateChain(alias);reader = new PdfReader(signPdfSrc);signPDFData = new ByteArrayOutputStream();// 临时pdf文件File temp = new File(signPdfSrcFile.getParent(), System.currentTimeMillis() + ".pdf");stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true); stp.setFullCompression();PdfSignatureAppearance sap = stp.getSignatureAppearance();sap.setReason("数字签名,不可改变");// 使用png格式透明图片Image image = Image.getInstance(signImage);sap.setImageScale(0);sap.setSignatureGraphic(image);sap.setRenderingMode(RenderingMode.GRAPHIC);// 是对应x轴和y轴坐标sap.setVisibleSignature( new Rectangle(x, y, x + 185, y + 68), 1,  UUID.randomUUID().toString().replaceAll("-", ""));stp.getWriter().setCompressionLevel(5);ExternalDigest digest = new BouncyCastleDigest();ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CADES);stp.close();reader.close();return signPDFData.toByteArray();} catch (Exception e) {e.printStackTrace();} finally {if (signPDFData != null) {try {signPDFData.close();} catch (IOException e) {}}if (fos != null) {try {fos.close();} catch (IOException e) {}}}return null;}public static void main(String[] args) throws Exception {byte[] fileData = sign("123456", "C:\\Users\\zhilin\\Desktop\\chat\\keystore.p12", //"C:\\Users\\zhilin\\Desktop\\chat\\filled.pdf",//"C:\\Users\\zhilin\\Desktop\\chat\\sign.jpg", 100, 290);FileOutputStream f = new FileOutputStream(new File("C:\\Users\\zhilin\\Desktop\\chat\\signed.pdf"));f.write(fileData);f.close();}}

3. 高清签章

高清签章是通过iText的绘制功能来完成。主要直接在PDF文件中绘制签章,代码实现如下:

    import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.security.KeyStore;import java.security.PrivateKey;import java.security.Security;import java.security.cert.Certificate;import org.bouncycastle.jce.provider.BouncyCastleProvider;import com.itextpdf.awt.AsianFontMapper;import com.itextpdf.text.BaseColor;import com.itextpdf.text.Element;import com.itextpdf.text.Font;import com.itextpdf.text.Paragraph;import com.itextpdf.text.Rectangle;import com.itextpdf.text.pdf.BaseFont;import com.itextpdf.text.pdf.ColumnText;import com.itextpdf.text.pdf.PdfReader;import com.itextpdf.text.pdf.PdfSignatureAppearance;import com.itextpdf.text.pdf.PdfStamper;import com.itextpdf.text.pdf.PdfStream;import com.itextpdf.text.pdf.PdfTemplate;import com.itextpdf.text.pdf.security.BouncyCastleDigest;import com.itextpdf.text.pdf.security.DigestAlgorithms;import com.itextpdf.text.pdf.security.ExternalDigest;import com.itextpdf.text.pdf.security.ExternalSignature;import com.itextpdf.text.pdf.security.MakeSignature;import com.itextpdf.text.pdf.security.MakeSignature.CryptoStandard;import com.itextpdf.text.pdf.security.PrivateKeySignature;public class SignHighPdf {/*** @param password*            秘钥密码* @param keyStorePath*            秘钥文件路径* @param signPdfSrc*            签名的PDF文件* @param x* * @param y* @return*/public static byte[] sign(String password, String keyStorePath, String signPdfSrc,    float x, float y,     String signText) {File signPdfSrcFile = new File(signPdfSrc);PdfReader reader = null;ByteArrayOutputStream signPDFData = null;PdfStamper stp = null;FileInputStream fos = null;try {BouncyCastleProvider provider = new BouncyCastleProvider();Security.addProvider(provider);KeyStore ks = KeyStore.getInstance("PKCS12", new BouncyCastleProvider());fos = new FileInputStream(keyStorePath);ks.load(fos, password.toCharArray()); // 私钥密码String alias = (String) ks.aliases().nextElement();PrivateKey key = (PrivateKey) ks.getKey(alias, password.toCharArray());Certificate[] chain = ks.getCertificateChain(alias);reader = new PdfReader(signPdfSrc);signPDFData = new ByteArrayOutputStream();// 临时pdf文件File temp = new File(signPdfSrcFile.getParent(), System.currentTimeMillis() + ".pdf");stp = PdfStamper.createSignature(reader, signPDFData, '\0', temp, true);PdfSignatureAppearance sap = stp.getSignatureAppearance();sap.setReason("数字签名,不可改变");// 是对应x轴和y轴坐标sap.setVisibleSignature(new Rectangle(x, y, x + 150, y + 65), 1,  "sr"+String.valueOf(System.nanoTime()));/layer 0 Creating the appearance for layer 0PdfTemplate n0 = sap.getLayer(0);n0.reset();float lx = n0.getBoundingBox().getLeft();float by = n0.getBoundingBox().getBottom();float width = n0.getBoundingBox().getWidth();float height = n0.getBoundingBox().getHeight();n0.setRGBColorFill(255, 0, 0);n0.rectangle(lx, by, 5, height);n0.rectangle(lx, by, width, 5);n0.rectangle(lx, by+height-5, width, 5);n0.rectangle(lx+width-5, by, 5, height);n0.fill();///layer 2PdfTemplate n2 = sap.getLayer(2);n2.setCharacterSpacing(0.0f);ColumnText ct = new ColumnText(n2);ct.setSimpleColumn(n2.getBoundingBox());n2.setRGBColorFill(255, 0, 0);//做一个占位的动作Paragraph p1 = new Paragraph(" ");BaseFont bf = BaseFont.createFont(AsianFontMapper.ChineseSimplifiedFont,AsianFontMapper.ChineseSimplifiedEncoding_H, BaseFont.NOT_EMBEDDED);Font font1 = new Font(bf, 5, Font.BOLD, BaseColor.RED);Font font2 = new Font(bf, 13, Font.BOLD, BaseColor.RED);p1.setFont(font1);ct.addElement(p1);Paragraph p = new Paragraph(signText);p.setAlignment(Element.ALIGN_CENTER);p.setFont(font2);ct.addElement(p);ct.go();stp.getWriter().setCompressionLevel(PdfStream.BEST_COMPRESSION);ExternalDigest digest = new BouncyCastleDigest();ExternalSignature signature = new PrivateKeySignature(key, DigestAlgorithms.SHA512, provider.getName());MakeSignature.signDetached(sap, digest, signature, chain, null, null, null, 0, CryptoStandard.CADES);stp.close();reader.close();return signPDFData.toByteArray();} catch (Exception e) {e.printStackTrace();} finally {if (signPDFData != null) {try {signPDFData.close();} catch (IOException e) {}}if (fos != null) {try {fos.close();} catch (IOException e) {}}}return null;}public static void main(String[] args) throws Exception {//对已经签章的signed.pdf文件再次签章,这次是高清签章byte[] fileData = sign("123456", "C:\\Users\\zhilin\\Desktop\\chat\\keystore.p12",//"C:\\Users\\zhilin\\Desktop\\chat\\signed.pdf", 350, 290, "华佗\n2017-12-20");FileOutputStream f = new FileOutputStream(new File("C:\\Users\\zhilin\\Desktop\\chat\\signed2.pdf"));f.write(fileData);f.close();}}

可以分析下下面这两个签章的区别,发现左边的签章很模糊,右边的特别清晰。

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

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

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

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

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

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

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

  4. adobe reader java_请问,如何用JAVA读PDF文件在浏览器中显示,不需要在本地系统中安装Adobe Reader。求java代码...

    JAVA读PDF可以实现,重点是如何在网页中显示PDF文件,而且不需要安装AdobeReader.没有安装AdobeReader,在网页显示PDF文件时,浏览器会提示下载.请问如何在网页中显示PDF文 ...

  5. java导出pdf文件并下载_java根据模板生成pdf文件并导出

    1.首先需要依赖包:itext的jar包,我是maven项目,所以附上maven依赖 [html] view plain copy com.itextpdf itextpdf 5.5.10 [html ...

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

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

  7. 1024程序员节|历经一个月总结使用java实现pdf文件的电子签字+盖章+防伪二维码+水印+PDF文件加密的全套解决方案

  8. Java实现pdf文件转图片

    Java实现pdf文件转图片 文章顺序是按照测试类- -Service- -Service实现类- -工具类- - POM依赖. test测试类里 pdfPath:存放pdf源文件的地方 imgflo ...

  9. Word制作生成html模板替换动态值为占位符使用Java转为pdf文件

    引言 最近开发遇到一个需求,公司法务给了一个word合同模板,需要替换里面的动态值为具体业务数据,然后生成pdf文件进行电子签章. 在网上找寻各种方法,发现很多都是需要特定工具,或者代码不全运行不起来 ...

最新文章

  1. ASP.NET 中HttpRuntime.Cache缓存数据
  2. c/c++ 避免重复包含 pragma once 和 #ifndef 的区别
  3. CTF web总结--利用mysql日志getshell
  4. 网站最令人讨厌的几个用户体验
  5. 学习CSS的背景图像属性background
  6. 容器(一)剖析面试最常见问题之 Java 集合框架
  7. 局域网上传文件到服务器很慢,win10局域网内传文件很慢怎么办_win10局域网内文件传输很慢如何处理-win7之家...
  8. JZOJ 5602. 【NOI2018模拟3.26】Cti JZOJ 5057. 【GDSOI2017模拟4.13】炮塔
  9. java中怎样验证重复文件_java – 如何在下载之前检查URL中的重复文件
  10. python爬虫从入门到精通
  11. k8s边缘节点_边缘计算,如何啃下集群管理这块硬骨头?
  12. FarPoint表格数字框中小数点位数的设置
  13. the android emulator process,Android studio报错:The emulator process for AVD (xxx) was killed
  14. 共轭梯度法(Conjugate Gradient)
  15. Socket Programming
  16. python iloc iat_python数据预处理_DataFrame数据筛选loc,iloc,ix,at,iat
  17. 计算机释放内存的命令,如何设置电脑Win7自动释放内存空间?
  18. android TabHost
  19. 什么软件可以测试电脑硬盘速度,硬盘速度测试软件
  20. Python标准库collections库:超好用的counter计数器,不接受反驳!

热门文章

  1. 左氨氯地平不是一种国产原研药吗为什么还要通过仿制药一致性评价
  2. [转载]论原著中白飞飞和朱七七两大奇女子_-刘艳红-_新浪博客
  3. 贪吃蛇python撞墙不死_不敢相信,60行python代码就写出了贪吃蛇游戏
  4. 极客与艺术:赢取 310 BTC 的正确解密方式
  5. linux进程pid分配规则,Linux进程pid分配法
  6. 树链剖分之长链剖分 详解 题目整理
  7. 我们网管自己不能贬低自己
  8. 嚼得菜根做得大事·《菜根谭》·三
  9. pinyin4j的基础使用
  10. 山东理工大学计算机考研录取名单,山东理工大学2019年研究生复试及拟录取结果...