依赖com.itextpdf

     <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.13</version></dependency><dependency><groupId>com.itextpdf.tool</groupId><artifactId>xmlworker</artifactId><version>5.5.13</version></dependency>

第一步:将指定的html内容转化成pdf文档

 /*** 将指定的html内容转化成pdf文档之后,写入到指定的输出流.*/public static void write(String htmlContent, OutputStream os) {if (htmlContent == null || htmlContent.length() == 0) {return;}if (os == null) {return;}htmlContent = getIntactHtml(htmlContent);doWrite(htmlContent, os);}/*** html完整内容的前缀标识*/private static final String INTACT_FLAG = "<html>";/*** html模板,当待转换的html只是片断时,需将其插入到模板的body内.*/private static final String TEMPLATE_HTML = "<html><head><style>h2,h3,h4{text-align: center}</style></head><body style=\"font-family:微软雅黑;\">${content}</body></html>";/*** 根据提供的html内容,获取完整的html内容.** @param htmlContent html内容* @return 完整的html内容*/private static String getIntactHtml(String htmlContent) {boolean intact = htmlContent.trim().toLowerCase().startsWith(INTACT_FLAG);if (!intact) {htmlContent = TEMPLATE_HTML.replaceFirst("\\$\\{content}", htmlContent);}return htmlContent;}// pdf密码private static final byte[] PASSWORD_BYTES = "password".getBytes();/*** 实施写操作.** @param htmlContent html内容* @param os          outputStream*/private static void doWrite(String htmlContent, OutputStream os) {InputStream is = new ByteArrayInputStream(htmlContent.getBytes(Charset.forName("UTF-8")));Document document = new Document();PdfWriter writer = null;try {writer = PdfWriter.getInstance(document, os);// 不可打印writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_PRINTING, STANDARD_ENCRYPTION_40);// 不可更改writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_MODIFY_CONTENTS, STANDARD_ENCRYPTION_40);// 不可复制writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_COPY, STANDARD_ENCRYPTION_40);// 不可注释writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_MODIFY_ANNOTATIONS, STANDARD_ENCRYPTION_40);// 不可填写表单域writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_FILL_IN, STANDARD_ENCRYPTION_40);// 不可页面提取writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_SCREENREADERS, STANDARD_ENCRYPTION_40);// 不可文档组合writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_ASSEMBLY, STANDARD_ENCRYPTION_40);// 不可签名writer.setEncryption(null, PASSWORD_BYTES, PdfWriter.ALLOW_DEGRADED_PRINTING, STANDARD_ENCRYPTION_40);// 标题document.addTitle("title");// 作者document.addAuthor("author");// 关键字document.addKeywords("keywords");// 主题document.addSubject("subject");document.open();// html设置<body style="font-family:微软雅黑;">// 或加载字体/*XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider() {@Overridepublic Font getFont(String fontname, String encoding, boolean embedded, float size, int style, BaseColor color) {//你的字体文件的位置//这里把所有字体都设置为宋体了,可以根据fontname的值设置字体String yaHeiFontName = "msyh.ttc";//如果是ttc需要这一行,ttf不需要yaHeiFontName += ",1";Font font = null;try {font = new Font(BaseFont.createFont(yaHeiFontName, BaseFont.IDENTITY_H, BaseFont.EMBEDDED));font.setStyle(style);font.setColor(color);if (size > 0) {font.setSize(size);}} catch (DocumentException | IOException e) {}return font;}};*/XMLWorkerHelper.getInstance().parseXHtml(writer, document, is, Charset.forName(CommonConstants.DEFAULT_ENCODING));} catch (DocumentException | IOException e) {throw new BizException(10061);} finally {IOUtils.closeQuietly(is);if (null != writer) {writer.flush();           }document.close();}}

第二步:签名

 private static final String KEYSTORE = "keystore.p12";// keystore密码private static final char[] PASSWORD = "xxxyyy".toCharArray();/*** @param src    需要签章的pdf文件路径* @param dest   签完章的pdf文件路径*            chain           证书链*            pk              签名私钥*            digestAlgorithm 摘要算法名称,例如SHA-1*            provider        密钥算法提供者,可以为null*            cryptoStandard  数字签名格式,itext有2种*            reason          签名的原因,显示在pdf签名属性中,随便填*            location        签名的地点,显示在pdf签名属性中,随便填* @throws GeneralSecurityException* @throws IOException* @throws DocumentException*/public static void sign(String src, String dest) throws GeneralSecurityException, IOException, DocumentException {// Creating the reader and the stamper,开始pdf readerPdfReader reader = new PdfReader(src, PASSWORD_BYTES);// 目标文件输出流FileOutputStream os = new FileOutputStream(dest);// 创建签章工具PdfStamper ,最后一个boolean参数// false的话,pdf文件只允许被签名一次,多次签名,最后一次有效// true的话,pdf可以被追加签名,验签工具可以识别出每次签名之后文档是否被修改PdfStamper stamper = PdfStamper.createSignature(reader, os, '\0', null, true);// 获取数字签章属性对象,设定数字签章的属性PdfSignatureAppearance appearance = stamper.getSignatureAppearance();String reason = "reason";String location = "location";appearance.setReason(reason);appearance.setLocation(location);// 设置签名的位置,页码,签名域名称,多次追加签名的时候,签名预名称不能一样// 签名的位置,是图章相对于pdf页面的位置坐标,原点为pdf页面左下角// 四个参数的分别是,图章左下角x,图章左下角y,图章右上角x,图章右上角y//appearance.setVisibleSignature(new Rectangle(450, 747, 550, 847), 1, "sig1");// 读取图章图片,这个image是itext包的image//Image image = Image.getInstance(new ClassPathResource(SIGNATURE).getFile().getAbsolutePath());//appearance.setSignatureGraphic(image);appearance.setCertificationLevel(PdfSignatureAppearance.NOT_CERTIFIED);// 设置图章的显示方式,如下选择的是只显示图章(还有其他的模式,可以图章和签名描述一同显示)appearance.setRenderingMode(PdfSignatureAppearance.RenderingMode.GRAPHIC);// 这里的itext提供了2个用于签名的接口,可以自己实现,后边着重说这个实现// 摘要算法ExternalDigest digest = new BouncyCastleDigest();// 签名算法String provider = null;String digestAlgorithm = DigestAlgorithms.SHA1;KeyStore ks = KeyStore.getInstance("PKCS12");InputStream inputStream = new ClassPathResource(KEYSTORE).getInputStream();ks.load(inputStream, PASSWORD);String alias = ks.aliases().nextElement();PrivateKey pk = (PrivateKey) ks.getKey(alias, PASSWORD);ExternalSignature signature = new PrivateKeySignature(pk, digestAlgorithm, provider);// 调用itext签名方法完成pdf签章MakeSignature.CryptoStandard cryptoStandard = MakeSignature.CryptoStandard.CMS;Certificate[] chain = ks.getCertificateChain(alias);MakeSignature.signDetached(appearance, digest, signature, chain, null, null, null, 0, cryptoStandard);// Closes the document. No more content can be written after the document is closed.stamper.close();inputStream.close();}

集成示例

 @RequestMapping(path = "pdf-get", method = RequestMethod.GET)public void getPdfContract(HttpServletResponse response) throws IOException {String fileName = "contract.pdf";response.setCharacterEncoding("UTF-8");response.setContentType("application/octet-stream");response.setHeader("Content-disposition", "attachment;filename=" + fileName);response.flushBuffer();File file = new File(fileName);// 需要填充的数据Object data = null;  ItextpdfUtils.generatePDFFromHtmlContent(template.getContent(), data, file);FileInputStream fileInputStream = new FileInputStream(file);byte b[] = new byte[1024];int j;ServletOutputStream os = response.getOutputStream();while ((j = fileInputStream.read(b)) != -1) {os.write(b, 0, j);os.flush();}fileInputStream.close();os.close();FileUtils.deleteQuietly(file);}/*** 把html形式的合同模板转换为PDF** @param content 合同模板内容-未设值* @param object  数据(对象/Map)*/public static void generatePDFFromHtmlContent(String content, Object object, File file) {File copyFile = new File("copy-" + file.getName());FileOutputStream os = null;try {if (!copyFile.exists()) {boolean result = copyFile.createNewFile();if (result) {LOG.info("The named copy file does not exist and was successfully created");} else {LOG.info("The named copy file already exists");}}// 如需要,可以使用freemarker对html文本进行数据填充,FreemarkerUtils可自行编写// content = FreemarkerUtils.parseString(content, object);os = new FileOutputStream(copyFile);// HTML转PDFItextpdfUtils.write(content, os);// 数字签名ItextpdfUtils.sign(copyFile.getAbsolutePath(), file.getAbsolutePath());} catch (IOException | GeneralSecurityException | DocumentException e) {LOG.error(e.getMessage());} finally {IOUtils.closeQuietly(os);FileUtils.deleteQuietly(copyFile);}}

使用itextpdf将html内容转PDF文档,并签章相关推荐

  1. 为什么大家都在用 PDF? PDF 文档怎么修改?

    "为什么我们用 PDF,不用 PPT?相近的功能,明明是 PPT 更方便修改呀!" 以 PDF 文档的格式将方案.报表.图文呈现给客户,似乎是职场上约定俗成的规则.这像是一个&qu ...

  2. 用Python提取解析pdf文档中内容

    用Python提取解析pdf文档中内容 文章目录: 参考: 1.https://blog.csdn.net/tmaczt/article/details/82876018 # Tika库 2.http ...

  3. Java使用PDFBox开发包实现对PDF文档内容编辑与保存

    pdfbox开发包下载地址:http://pdfbox.apache.org/ 程序实现了PDF文档的创建,读入,与修改PDF内容并保存. 可能有个前提,PDF文档不是加密的,如果加密怎么办,我没研究 ...

  4. 使用HttpHandler解析并展示PDF文档内容

    前言 如果我们想将服务端的PDF文档内容展示给客户端,往往会通过URL直接访问的方式.这样一来,PDF文档就会毫无保留的保存到客户端去,通过浏览器的PDF插件,客户端可以随意拷贝PDF的副本.(如下图 ...

  5. java中operationBox_Java使用PDFBox开发包实现对PDF文档内容编辑与保存

    pdfbox开发包下载地址:http://pdfbox.apache.org/ 程序实现了PDF文档的创建,读入,与修改PDF内容并保存. 可能有个前提,PDF文档不是加密的,如果加密怎么办,我没研究 ...

  6. 怎样在页面上查找请求内容_怎样快速裁剪删除PDF文档的页面内容?

    有时在编辑PDF文档时,有大段的内容需要删除,且又不是整页无法直接通过删除页面解决,特别是扫描件无法直接用delete键清除时,有什么办法能快速解决呢?如何直接裁切不需要或保留需要的内容部分呢? 首先 ...

  7. HttpHandler解析并展示PDF文档内容

    2019独角兽企业重金招聘Python工程师标准>>> HttpHandler 解析并展示 PDF 文档内容 如果我们想将服务端的 PDF 文档内容展示给客户端,往往会通过 URL ...

  8. 编辑PDF文档内容有哪些方法

    PDF文件采用的是字型嵌入系统,能将字型随文件一起进行传输,所以文档在浏览查看以及传输上要优于word文档文档格式,但是这种文档在编辑的时候就没那样简单了,要是在遇到PDF格式的文档需要编辑该怎样去处 ...

  9. java操作office和pdf文件java读取word,excel和pdf文档内容

    在平常应用程序中,对office和pdf文档进行读取数据是比较常见的功能,尤其在很多web应用程序中.所以今天我们就简单来看一下Java对word.excel.pdf文件的读取.本篇博客只是讲解简单应 ...

最新文章

  1. [认证授权] 5.OIDC(OpenId Connect)身份认证授权(扩展部分)
  2. w ndows8怎么连接网络,(Wndows8.1优化设置全面解析.doc
  3. 引:善用backtrace解决大问题
  4. 今天我开通了51cto的博客
  5. 2018年工业机器人销量排位_报告显示中国工业机器人销量排名世界前三
  6. 保存最大的前20项暴力--Heritage of skywalkert
  7. docker学习记录 docker 脚本----gitlab,nexus3(二)
  8. centos6安装mysql并远程连接_Linux中Mysql不支持远程连接解决办法
  9. 【二分答案】【中位数】codeforces 394 bun
  10. 基于TCP/IP的IEC60870-5-104远动通信协议
  11. 在线教育开源源码:消费者如何规避线上教育“陷阱”营销?
  12. html 编辑cad图,cad制图是什么
  13. Three.js点击地图动态标注
  14. 第七章 1什么是活动目录?活动目录有那些优点?
  15. 项目实战|史上最简单的springboot 整合elk教程,实现日志收集(带视频哦)
  16. 什么是计算机网络AP,无线AP是什么
  17. python可以数独游戏吗_简单实现python数独游戏
  18. 中国网络教育行业市场需求及十四五发展新挑战研究报告2021-2027年
  19. VMware上安装centOS,能ping通本地,但是ping不了外网怎么办
  20. 数据治理管理平台的5种能力

热门文章

  1. 2017-12-01 中英文代码对比之ZLOGO 4 LOGO
  2. 在angular7中HTML动态加载背景图片
  3. 在saye“满月”接受建议
  4. 超方便的 IndexDB 库
  5. 【泛型】泛型上下边界
  6. 计算机及编码教案,高中信息技术《文字及其处理技术-汉字的编码》教案
  7. Themeleaf做判断
  8. 数据错误循环冗余检查是什么意思_数据库为什么会丢失数据
  9. 安装Windows+Ubuntu18.04双系统(双盘)及grub引导修复
  10. 网络扫盲——NAT(网络地址转换)