依赖引入
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.21</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
代码示例
import com.itextpdf.text.BadElementException;
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 com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import lombok.extern.slf4j.Slf4j;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
/**
* @description: PDF印章工具类
*/
@Slf4j
//@Component
//@RequiredArgsConstructor
public class PdfSignetUtil {
// private final RedisCache redisCache;
public static void headAddSignSeal(String sourceFilePath, String targetFilePath, String imagePath, int type) {
// 加载印章图片
Image image;
try {
image = Image.getInstance(imagePath);
} catch (BadElementException | IOException e) {
log.error("com.aistreamrpa.xtp2.main.util.PdfSignetUtil.headAddSignSeal,{}, 印章图片读取失败", imagePath, e);
throw new RuntimeException("印章图片读取失败");
}
float fit = type == 1 ? 100 : 140;
image.scaleToFit(fit, fit);
PdfReader pdfReader = null;
PdfStamper stamper = null;
String outputPath = (targetFilePath == null || targetFilePath.isEmpty()) ? sourceFilePath + ".tmp" : targetFilePath;
Path source = Paths.get(outputPath);
try {
// 读取PDF文件
pdfReader = new PdfReader(sourceFilePath);
stamper = new PdfStamper(pdfReader, Files.newOutputStream(source));
// 获取首页尺寸
PdfContentByte content = stamper.getOverContent(1);
Rectangle pageSize = pdfReader.getPageSize(1);
// 设置印章位置在右上角
// 485.3 为文件印章的x轴,后续可以使用redis存取而不是写死
float x = type == 1 ? pageSize.getWidth() - image.getScaledWidth() - 10 : (float) (485.3 - image.getScaledWidth());
float y = pageSize.getHeight() - image.getScaledHeight() - 10;
image.setAbsolutePosition(x, y);
// 添加图像到首页
content.addImage(image);
} catch (DocumentException | IOException e) {
log.error("com.aistreamrpa.xtp2.main.util.PdfSignetUtil.headAddSignSeal,{}, 源文件读取失败", sourceFilePath, e);
throw new RuntimeException(e);
} finally {
if (stamper != null) {
try {
stamper.close();
} catch (DocumentException | IOException e) {
log.error("com.aistreamrpa.xtp2.main.util.PdfSignetUtil.headAddSignSeal,关闭 PdfStamper 失败", e);
}
}
if (pdfReader != null) {
pdfReader.close();
}
}
// 如果targetFilePath为空,替换原文件
if (targetFilePath == null || targetFilePath.isEmpty()) {
try {
Files.move(source, Paths.get(sourceFilePath), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
log.error("com.aistreamrpa.xtp2.main.util.PdfSignetUtil.headAddSignSeal,替换原文件失败", e);
throw new RuntimeException("替换原文件失败");
}
}
}
/**
* 是否包含印章,不包含则添加
* 如果目标文件路径为空,则将文件直接覆盖源文件
*
* @param sourceFilePath 源文件路径
* @param targetFilePath 目标文件路径
* @param imagePath 印章图片路径
* @param type 1.文件章 2.受控分发章
* @return 是否成功
*/
public static boolean whetherIsIncludedOfSeal(String sourceFilePath, String targetFilePath, String imagePath, int type) {
File pdfFile = new File(sourceFilePath);
File imageFile = new File(imagePath);
if(!pdfFile.exists() || !imageFile.exists()){
throw new RuntimeException("图片路径 or 源文件路径 不存在");
}
// 加载指定的图片
BufferedImage specifiedImage;
try {
specifiedImage = ImageIO.read(imageFile);
} catch (IOException e) {
log.error("com.aistreamrpa.xtp2.main.util.PdfSignetUtil.whetherIsIncludedOfSeal,{}, 图片读取失败", imagePath, e);
throw new RuntimeException("图片读取失败");
}
PdfDocument pdfDocument = new PdfDocument();
//载入PDF文档
pdfDocument.loadFromFile(sourceFilePath);
PdfPageBase pdfPageBase = pdfDocument.getPages().get(0);
BufferedImage[] bufferedImages = pdfPageBase.extractImages();
// 比较提取的图片与指定图片
boolean containsImage = false;
for (BufferedImage image : bufferedImages) {
if (imagesAreEqual(image, specifiedImage)) {
containsImage = true;
break;
}
}
// 印章不存在,添加印章
if (!containsImage) {
headAddSignSeal(sourceFilePath, targetFilePath, imagePath,type);
containsImage = true;
}
return containsImage;
}
private static boolean imagesAreEqual(BufferedImage imgA, BufferedImage imgB) {
if (imgA.getWidth() != imgB.getWidth() || imgA.getHeight() != imgB.getHeight()) {
return false;
}
for (int y = 0; y < imgA.getHeight(); y++) {
for (int x = 0; x < imgA.getWidth(); x++) {
if (imgA.getRGB(x, y) != imgB.getRGB(x, y)) {
return false;
}
}
}
return true;
}
}