Java-使用 OpenPDF 给 PDF 添加水印

2024年06月25日 15:19 · 阅读(427) ·

开发环境

名称 版本
操作系统 Windows 10 X64
JDK JDK1.8(jdk-8u151-windows-x64)
IntelliJ IDEA IntelliJ IDEA 2022.3
Maven Maven 3.9.4

参考及重要说明

Java-使用 iText 给 PDF 添加水印

因为 iText 有版权问题导致不能继续使用,所以使用 OpenPDF 来替换 iText 相关功能。

pom.xml

  1. <!--Open PDF -->
  2. <dependency>
  3. <groupId>com.github.librepdf</groupId>
  4. <artifactId>openpdf</artifactId>
  5. <version>1.3.34</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.github.librepdf</groupId>
  9. <artifactId>openpdf-fonts-extra</artifactId>
  10. <version>1.3.34</version>
  11. </dependency>
  12. <!--PDF 加密-->
  13. <dependency>
  14. <groupId>org.bouncycastle</groupId>
  15. <artifactId>bcprov-ext-jdk15on</artifactId>
  16. <version>1.47</version>
  17. </dependency>

PDF 参数类-PDFParamsDTO

参考:PDF 参数类-PDFParamsDTO

PDF 工具类-PDFMakerUtil

  1. package com.atguigu.boot3.actuator.util;
  2. import com.atguigu.boot3.actuator.dto.PDFParamsDTO;
  3. import com.lowagie.text.Element;
  4. import com.lowagie.text.Rectangle;
  5. import com.lowagie.text.pdf.*;
  6. import lombok.Data;
  7. import lombok.extern.slf4j.Slf4j;
  8. import javax.swing.*;
  9. import java.awt.*;
  10. import java.io.ByteArrayOutputStream;
  11. import java.io.FileOutputStream;
  12. import java.io.File;
  13. import java.io.InputStream;
  14. import io.micrometer.common.util.StringUtils;
  15. import java.nio.file.Files;
  16. import java.nio.file.Paths;
  17. /**
  18. * OpenPDF 生成类
  19. * - luoma - 2024年6月25日11:26:38
  20. */
  21. @Data
  22. @Slf4j
  23. public class OpenPDFMakerUtil {
  24. /**
  25. * 使用 OpenPDF 给 PDF 文件添加水印,旋转,透明度,密码
  26. *
  27. * @param pdfParams PDF 参数类
  28. * @return 添加水印后的 PDF 文件字节数组(添加到本地的情况为空)
  29. */
  30. public static byte[] addWatermarkAuto(PDFParamsDTO pdfParams) {
  31. String methodName = "addWatermarkAuto >> OpenPDF 添加水印 >> ";
  32. //返回结果
  33. byte[] byteArray = null;
  34. try {
  35. log.info("{}开始调用 >> 入参:【pdfParams = {}】", methodName, pdfParams);
  36. //坐标
  37. float x = pdfParams.getX();
  38. float y = pdfParams.getY();
  39. float angle = pdfParams.getAngle();
  40. //文字颜色
  41. int r = pdfParams.getR();
  42. int g = pdfParams.getG();
  43. int b = pdfParams.getB();
  44. RGBColor fontColor = new RGBColor(r, g, b);
  45. //文字大小
  46. int fontSize = pdfParams.getDefaultFontSize();
  47. //文字内容
  48. // 使用"||"将内容进行分割
  49. String waterMarkName = pdfParams.getWatermark();
  50. String[] waterMarkContents = waterMarkName.split("\\|\\|");
  51. //获取水印文字的最大高度和宽度
  52. int textH = 0, textW = 0;
  53. for (String waterMarkContent : waterMarkContents) {
  54. JLabel label = new JLabel();
  55. label.setText(waterMarkContent);
  56. FontMetrics metrics = label.getFontMetrics(label.getFont());
  57. if (textH < metrics.getHeight()) {
  58. textH = metrics.getHeight();
  59. }
  60. if (textW < metrics.stringWidth(label.getText())) {
  61. textW = metrics.stringWidth(label.getText());
  62. }
  63. }
  64. //设置输入,输出
  65. PdfReader reader;
  66. PdfStamper stamper;
  67. ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
  68. if (pdfParams.getGenerateToLocal()) {
  69. //输入目录
  70. String inputFile = pdfParams.getTemplatePath();
  71. //输出目录
  72. String outputFile = pdfParams.getFileDirectory();
  73. //设置输入,输出
  74. reader = new PdfReader(inputFile);
  75. stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(outputFile)));
  76. } else {
  77. //设置输入,输出
  78. InputStream inputStream = pdfParams.getInputStream();
  79. reader = new PdfReader(inputStream);
  80. stamper = new PdfStamper(reader, outputStream);
  81. }
  82. // 设置密码文件打开密码文件编辑密码
  83. byte[] arrUserPassword = null;
  84. byte[] arrOwnerPassword = null;
  85. if (StringUtils.isNotBlank(pdfParams.getUserPassword())) {
  86. arrUserPassword = pdfParams.getUserPassword().getBytes();
  87. }
  88. if (StringUtils.isNotBlank(pdfParams.getOwnerPassword())) {
  89. arrOwnerPassword = pdfParams.getOwnerPassword().getBytes();
  90. }
  91. if (StringUtils.isNotBlank(pdfParams.getUserPassword()) || StringUtils.isNotBlank(pdfParams.getOwnerPassword())) {
  92. stamper.setEncryption(arrUserPassword, arrOwnerPassword, PdfWriter.ALLOW_PRINTING, false);
  93. }
  94. //设置字体
  95. BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
  96. // 获取总页数 +1, 下面从1开始遍历
  97. int total = reader.getNumberOfPages() + 1;
  98. PdfContentByte under;
  99. for (int i = 1; i < total; i++) {
  100. // 在内容上方加水印
  101. under = stamper.getOverContent(i);
  102. // 在内容下方加水印
  103. //under = stamper.getUnderContent(i);
  104. under.saveState();
  105. under.beginText();
  106. under.setFontAndSize(baseFont, fontSize);
  107. //文字加粗
  108. //设置文本描边宽度
  109. //under.setLineWidth(0.3);
  110. //设置文本为描边模式, 会导致 setColorFill 颜色失效
  111. //under.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
  112. //字体颜色
  113. under.setColorFill(fontColor);
  114. // 设置透明度
  115. PdfGState gs = new PdfGState();
  116. gs.setFillOpacity(pdfParams.getFillOpacity());
  117. under.setGState(gs);
  118. //水印字体和大小
  119. Rectangle pageRect = reader.getPageSizeWithRotation(i);
  120. int width1 = (int) pageRect.getWidth();
  121. int height1 = (int) pageRect.getHeight();
  122. //fontSize = (width1 + height1) / pdfParams.getDefaultFontSize();
  123. x = (float) (width1) / 2;
  124. y = (float) height1 / 2;
  125. // 将分段的字段进行输出编写
  126. for (int z = 0; z < waterMarkContents.length; z++) {
  127. //文字
  128. String itemWaterMark = waterMarkContents[z];
  129. // 间隔距离(参数可调节)
  130. int interval = fontSize * z;
  131. under.showTextAligned(Element.ALIGN_CENTER, itemWaterMark, x, y - (interval + textH * z), angle);
  132. }
  133. // 添加水印文字
  134. under.endText();
  135. }
  136. stamper.close();
  137. reader.close();
  138. //outputStream 转换为 byte
  139. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  140. outputStream.writeTo(byteArrayOutputStream);
  141. byteArray = byteArrayOutputStream.toByteArray();
  142. log.info("{}结束调用,返回结果:{}", methodName, "OK");
  143. } catch (Exception e) {
  144. log.error("{}调用异常 >> 入参:【pdfParams = {}】,e:", methodName, pdfParams, e);
  145. }
  146. return byteArray;
  147. }
  148. }

测试代码及结果

参考:测试代码及结果