公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
自动签章的公告、合同文件等形式的文档在公司中有非常多的使用场景。随着电子签章的流行,越来越多的公司,才有这些功能。基于此,本文使用 Java 来实现 pdf 合同文件自动签章。
本文只是一个 demo,若需完成的细节功能,可以加我微信:xmtxtt,送给爱学习研究的网友们。
下面开始正文。
pom依赖
首先是引入依赖。
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.11</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.2.0</version>
</dependency>
关键字信息查找
package com.xttblog.demo.pdfSign;
import cn.hutool.core.collection.CollectionUtil;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.canvas.parser.PdfCanvasProcessor;
import com.itextpdf.kernel.pdf.canvas.parser.listener.IPdfTextLocation;
import com.itextpdf.kernel.pdf.canvas.parser.listener.RegexBasedLocationExtractionStrategy;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FindKey {
/**
* 获取关键字位置信息map
* key为页数,value为当页关键字信息集合
*/
public static Map<Integer, List<KeyWordInfo>> keyWordLocationMap(String input, String keyword) {
Map<Integer, List<KeyWordInfo>> listMap;
try(PdfReader reader = new PdfReader(input);PdfDocument pdfDocument = new PdfDocument(reader)) {
int pageNumbers = pdfDocument.getNumberOfPages();
listMap = new HashMap<>(pageNumbers);
for (int i = 1; i <= pageNumbers; i++) {
PdfPage page = pdfDocument.getPage(i);
RegexBasedLocationExtractionStrategy strategy = new RegexBasedLocationExtractionStrategy(keyword);
PdfCanvasProcessor canvasProcessor = new PdfCanvasProcessor(strategy);
canvasProcessor.processPageContent(page);
Collection<IPdfTextLocation> resultantLocations = strategy.getResultantLocations();
//自定义结果处理
if (!resultantLocations.isEmpty()) {
List<KeyWordInfo> keyWordInfoList = new ArrayList<>();
List<IPdfTextLocation> iPdfTextLocationList = CollectionUtil.newArrayList(resultantLocations);
for (int m = 0; m < iPdfTextLocationList.size(); m++) {
IPdfTextLocation item = iPdfTextLocationList.get(m);
Rectangle boundRectangle = item.getRectangle();
KeyWordInfo keyWordInfo = new KeyWordInfo();
keyWordInfo.setPage(i);
keyWordInfo.setX(boundRectangle.getX());
keyWordInfo.setY(boundRectangle.getY());
keyWordInfo.setWidth(boundRectangle.getWidth());
keyWordInfo.setHeight(boundRectangle.getHeight());
keyWordInfo.setText(item.getText());
keyWordInfo.setNum(m + 1);
System.out.println("关键字“" + keyword + "” 的坐标为 x: " + boundRectangle.getX() + " ,y: " + boundRectangle.getY());
keyWordInfoList.add(keyWordInfo);
}
listMap.put(i, keyWordInfoList);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return listMap;
}
}
package com.xttblog.demo.pdfSign;
import lombok.Data;
@Data
public class KeyWordInfo{
private float x;
private float y;
private float width;
private float height;
/**
* pdf的页面
*/
private int page;
/**
* 当前页面中第几个
*/
private int num;
private String text;
}
关键字签章、指定位置签章demo
package com.xttblog.pdfSign;
import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Date;
import java.util.List;
import java.util.Map;
public class ItextTest {
/**
* 指定位置盖章
*/
public static void main1(String[] args) throws Exception {
String dateStr = DateUtil.format(new Date(),"yyyyMMdd-HHmm");
String inputPdf = "D://test//pdf//test2.pdf";
String outputPdf = "D://test//pdf//指定位置签章-itext-".concat(dateStr).concat(".pdf");
String stampImage ="D://test//pdf//zhang.png";
ByteArrayOutputStream memoryStream = readFileToMemoryStream(inputPdf);
PdfReader reader = new PdfReader(memoryStream.toByteArray());
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdf));
Image image = Image.getInstance(stampImage);
//设置签字图片宽高
image.scaleToFit(100, 100);
PdfContentByte content;
Rectangle pageSize;
int pageCount = reader.getNumberOfPages();
for(int i=1; i <= pageCount; i++) {
pageSize = reader.getPageSizeWithRotation(i);
content = stamper.getOverContent(i);
//签章图片位置坐标
float absoluteX = 10;
float absoluteY = pageSize.getHeight() - image.getScaledHeight() - 10;
image.setAbsolutePosition( absoluteX, absoluteY );
content.addImage(image);
}
stamper.close();
reader.close();
}
/**
* 关键字盖章
*/
public static void main(String[] args) throws IOException, DocumentException {
String dateStr = DateUtil.format(new Date(),"yyyyMMdd-HHmm");
String inputPdf = "D://test//pdf//test2.pdf";
String outputPdf = "D://test//pdf//关键字签章-itext-".concat(dateStr).concat(".pdf");
String stampImage ="D://test//pdf//zhang.png";
// 要盖章的关键字
String keyword = "张三看看";
// 关键字位置信息map
Map<Integer, List<KeyWordInfo>> map = FindKey.keyWordLocationMap(inputPdf,keyword);
ByteArrayOutputStream memoryStream = readFileToMemoryStream(inputPdf);
PdfReader pdfReader = new PdfReader(memoryStream.toByteArray());
PdfStamper pdfStamper = new PdfStamper(pdfReader, Files.newOutputStream(Paths.get(outputPdf)));
Image image = Image.getInstance(stampImage);
//设置签字图片宽高
image.scaleAbsolute(100, 100);
int pageCount = pdfReader.getNumberOfPages();
for(int i=1; i <= pageCount; i++) {
PdfContentByte content = pdfStamper.getUnderContent(i);
List<KeyWordInfo> list = map.get(i);
for (KeyWordInfo keyWordInfo : list) {
//签章图片位置坐标
float absoluteX = keyWordInfo.getX() + keyWordInfo.getWidth()/2 - image.getScaledWidth()/2 ;
float absoluteY = keyWordInfo.getY() + keyWordInfo.getHeight()/2 - image.getScaledHeight()/2;
image.setAbsolutePosition(absoluteX, absoluteY);
content.addImage(image);
}
}
pdfStamper.close();
pdfReader.close();
}
private static ByteArrayOutputStream readFileToMemoryStream(String filePath) throws IOException {
ByteArrayOutputStream memoryStream = new ByteArrayOutputStream();
// 缓冲区大小
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream(filePath)) {
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
memoryStream.write(buffer, 0, bytesRead);
}
}
return memoryStream;
}
}
效果
实现思路总结
为了实现“pdf盖章”,我们需要按照以下步骤进行操作。
- 取原始pdf文件
- 读取盖章图片
- 在pdf文件中指定位置盖章
- 保存新的pdf文件
读取原始pdf文件
首先,我们需要读取原始的pdf文件。我们可以使用Apache PDFBox、itextpdf等库来实现这一步。
// 导入PDFBox库import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.pdmodel.PDPage;// 读取pdf文件PDDocument document = PDDocument.load(new File("original.pdf"));
读取盖章图片
接下来,我们需要读取用于盖章的图片。我们可以使用Java ImageIO库来实现这一步。
// 导入ImageIO库import javax.imageio.ImageIO;import java.awt.image.BufferedImage;// 读取盖章图片BufferedImage stampImage = ImageIO.read(new File("stamp.png"));
在pdf文件中指定位置盖章
现在,我们需要在pdf文件中的指定位置盖章。我们可以使用PDFBox、itextpdf等库来实现这一步。
// 获取pdf页面PDPage page = document.getPage(0);// 在指定位置盖章// 假设在(100, 100)位置盖章page.getContents().add(new PDStamp(stampImage, 100, 100));
保存新的pdf文件
最后,我们需要保存新的pdf文件。我们可以使用PDFBox、itextpdf等库来实现这一步。
// 保存新的pdf文件document.save("stamped.pdf");document.close();
整体来说,都是比较简单的。比较关键的是要找出关键字位置。
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » Java 实现 pdf 合同文件自动签章