ks3887 发表于 2024-1-5 18:18

在pdf中指定位置添加二维码

前言:
需求如下
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 = 10000
#要添加二维码的文件夹

INIT_FILE_PATH = /Users/admin/Downloads/1
#最终输出文件夹

OUT_PUT_FILE_PATH = /Users/admin/Downloads/2/
#二维码添加坐标 -> left距离PDF左边,top距离PDF顶部,单位毫米

left=12
top=4.5
#pdf尺寸 -> width宽,height高,单位cm

width=32
height=45.2

```

jr001 发表于 2024-1-5 18:26

感谢分享

moruye 发表于 2024-1-5 19:51

sdieedu 发表于 2024-1-6 07:06

很实用很好

zhangting2022 发表于 2024-1-6 07:21

感谢感谢分享

suhaoyue 发表于 2024-1-6 07:24

感谢分享

CQGaxm 发表于 2024-1-6 07:24

学习学习,感谢分享

Threesui 发表于 2024-1-6 08:19

谢谢分享,比较实用

hui521 发表于 2024-1-6 15:34

感谢分享,学习学习

Siycd 发表于 2024-1-8 01:47

谢谢分享,比较实用
页: [1] 2
查看完整版本: 在pdf中指定位置添加二维码