大神论坛

找回密码
快速注册
查看: 78 | 回复: 0

[源码] 用JAVA实现在pdf中指定位置添加二维码 附源码

主题

帖子

0

积分

初入江湖

UID
686
积分
0
精华
威望
0 点
违规
大神币
68 枚
注册时间
2023-10-14 10:56
发表于 2024-01-05 22:28
本帖最后由 wystudio 于 2024-01-05 22:28 编辑

前言:
需求如下
1.监控a文件夹中的文件提取文件名前9位
2.需要自动屏蔽第二位,剩余8位数
3.生成为二维码-L纠错级别,码版本21*21的常用二维码
4.将二维码嵌入pdf每页的指定位置
5.导出新的pdf文件,并且将原来文件名称添加-已处理,文件输出新的文件
其中部分参数可配置方式完成(具体配置放下面)
代码如下:

public void addQRcodeToPDF() {
try {
String property = System.getProperty("user.dir");
String configName = property + "/pdf.ini";
Wini ini = new Wini(new File(configName));
log.info("get pdf.ini {}", ini);
String sleepTime = ini.get("SLEEP_TIME", "SLEEP_TIME");
String initFilePath = ini.get("INIT_FILE_PATH", "INIT_FILE_PATH");

// 以页面左下角为原点的 x 坐标
float x = Float.parseFloat(ini.get("QR_LOCATION", "left"));
// 以页面左下角为原点的 y 坐标
float y = Float.parseFloat(ini.get("QR_LOCATION", "top"));
float height = Float.parseFloat(ini.get("PDF_SIZE", "height"));
String outputPath = ini.get("OUT_PUT_FILE_PATH", "OUT_PUT_FILE_PATH");
File initFile = new File(initFilePath);
File[] list = initFile.listFiles();
if (initFile.exists() && initFile.isDirectory()) {
for (File file : list) {
String fileName = file.getName();
if (fileName.contains("已处理")) {
continue;
}
// 构建保存文件的路径,将文件保存到目标文件夹
String outputFilePath = outputPath + fileName;

if (!isFirstNineDigits(fileName)) {
log.info("file name is not a 9-digit number, skip {}", fileName);
continue;
}

log.info("正在处理 pdf {} 文件", fileName);
String fileNumber = fileName.substring(0, 9);
String number = fileNumber.charAt(0) + fileNumber.substring(2);
BufferedImage bufferedImage = generateQRCode(number);

PdfReader reader = new PdfReader(file.getAbsolutePath());
Document document = new Document();
// 创建一个输出文件
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFilePath));

// 创建一个 Image 对象,用于插入到 PDF 中
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
Image image = Image.getInstance(bufferedImage, null);

// 图像的宽度和高度(毫米)
float imageHeightMm = 8f;

// 将毫米转换为厘米
float mmToCm = 0.1f;

// 计算图像的左上角位置
float imageLeftCm = x * mmToCm;
float imageTopCm = height - (y * mmToCm) - (imageHeightMm * mmToCm);

image.setAbsolutePosition(imageLeftCm * 28.3465f, imageTopCm * 28.3465f);

// 获取当前页的 PdfContentByte
PdfContentByte content = stamper.getOverContent(i);
content.addImage(image);
}

stamper.close();
document.close();
reader.close();
log.info("PDF 更新成功,已保存到 {}", outputPath);
if (!file.exists()) {
log.error("源文件不存在 {}", fileName);
continue;
}
fileName = "已处理-" + fileName;

String path = file.getParentFile().getPath() + "/" + fileName;
File newFile = new File(path);
if (newFile.exists()) {
log.error("新文件名已存在。 {}", newFile.getName());
continue;
}
boolean success = file.renameTo(newFile);
if (!success) {
log.info("文件重命名失败 {}", fileName);
}
}
}
log.info("本次任务完成!即将进行" + Integer.valueOf(sleepTime) + "秒休眠");
Thread.sleep(Integer.valueOf(sleepTime));
} catch (Exception e) {
log.error("addQRcodeToPDF error!", e);
}
}

public static boolean isFirstNineDigits(String str) {
if (str == null || str.length() < 9) {
return false;
}

String firstNineDigits = str.substring(0, 9);
return firstNineDigits.matches("\\d+");
}

private static BufferedImage generateQRCode(String data) {
try {
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.MARGIN, 0); // 设置二维码边距为0
hints.put(EncodeHintType.ERROR_CORRECTION, com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.L); // 设置纠错级别为L
//设置二维码尺寸为21像素
BitMatrix matrix = new MultiFormatWriter().encode(data, BarcodeFormat.QR_CODE, 21, 21, hints);
BufferedImage image = toBufferedImage(matrix);
return image;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

private static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

// 将 BitMatrix 转换为 BufferedImage
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, matrix.get(x, y) ? Color.BLACK.getRGB() : Color.WHITE.getRGB());
}
}

return image;
}

pom坐标

<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.6</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>

pdf.ini配置

#线程休眠时间 -> 执行完一次之后休息10000毫秒
[SLEEP_TIME]
SLEEP_TIME = 10000
#要添加二维码的文件夹
[INIT_FILE_PATH]
INIT_FILE_PATH = /Users/admin/Downloads/1
#最终输出文件夹
[OUT_PUT_FILE_PATH]
OUT_PUT_FILE_PATH = /Users/admin/Downloads/2/
#二维码添加坐标 -> left距离PDF左边,top距离PDF顶部,单位毫米
[QR_LOCATION]
left=12
top=4.5
#pdf尺寸 -> width宽,height高,单位cm
[PDF_SIZE]
width=32
height=45.2


注:若转载请注明大神论坛来源(本贴地址)与作者信息。

返回顶部