开发环境
名称 | 版本 |
---|---|
操作系统 | Windows 10 X64 |
JDK | JDK1.8(jdk-8u151-windows-x64) |
IntelliJ IDEA | IntelliJ IDEA 2022.3 |
Maven | Maven 3.9.4 |
参考及重要说明
因为 iText 有版权问题导致不能继续使用,所以使用 OpenPDF 来替换 iText 相关功能。
pom.xml
<!--Open PDF -->
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf</artifactId>
<version>1.3.34</version>
</dependency>
<dependency>
<groupId>com.github.librepdf</groupId>
<artifactId>openpdf-fonts-extra</artifactId>
<version>1.3.34</version>
</dependency>
<!--PDF 加密-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-ext-jdk15on</artifactId>
<version>1.47</version>
</dependency>
PDF 参数类-PDFParamsDTO
PDF 工具类-PDFMakerUtil
package com.atguigu.boot3.actuator.util;
import com.atguigu.boot3.actuator.dto.PDFParamsDTO;
import com.lowagie.text.Element;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import javax.swing.*;
import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.File;
import java.io.InputStream;
import io.micrometer.common.util.StringUtils;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* OpenPDF 生成类
* - luoma - 2024年6月25日11:26:38
*/
@Data
@Slf4j
public class OpenPDFMakerUtil {
/**
* 使用 OpenPDF 给 PDF 文件添加水印,旋转,透明度,密码
*
* @param pdfParams PDF 参数类
* @return 添加水印后的 PDF 文件字节数组(添加到本地的情况为空)
*/
public static byte[] addWatermarkAuto(PDFParamsDTO pdfParams) {
String methodName = "addWatermarkAuto >> OpenPDF 添加水印 >> ";
//返回结果
byte[] byteArray = null;
try {
log.info("{}开始调用 >> 入参:【pdfParams = {}】", methodName, pdfParams);
//坐标
float x = pdfParams.getX();
float y = pdfParams.getY();
float angle = pdfParams.getAngle();
//文字颜色
int r = pdfParams.getR();
int g = pdfParams.getG();
int b = pdfParams.getB();
RGBColor fontColor = new RGBColor(r, g, b);
//文字大小
int fontSize = pdfParams.getDefaultFontSize();
//文字内容
// 使用"||"将内容进行分割
String waterMarkName = pdfParams.getWatermark();
String[] waterMarkContents = waterMarkName.split("\\|\\|");
//获取水印文字的最大高度和宽度
int textH = 0, textW = 0;
for (String waterMarkContent : waterMarkContents) {
JLabel label = new JLabel();
label.setText(waterMarkContent);
FontMetrics metrics = label.getFontMetrics(label.getFont());
if (textH < metrics.getHeight()) {
textH = metrics.getHeight();
}
if (textW < metrics.stringWidth(label.getText())) {
textW = metrics.stringWidth(label.getText());
}
}
//设置输入,输出
PdfReader reader;
PdfStamper stamper;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
if (pdfParams.getGenerateToLocal()) {
//输入目录
String inputFile = pdfParams.getTemplatePath();
//输出目录
String outputFile = pdfParams.getFileDirectory();
//设置输入,输出
reader = new PdfReader(inputFile);
stamper = new PdfStamper(reader, Files.newOutputStream(Paths.get(outputFile)));
} else {
//设置输入,输出
InputStream inputStream = pdfParams.getInputStream();
reader = new PdfReader(inputStream);
stamper = new PdfStamper(reader, outputStream);
}
// 设置密码文件打开密码文件编辑密码
byte[] arrUserPassword = null;
byte[] arrOwnerPassword = null;
if (StringUtils.isNotBlank(pdfParams.getUserPassword())) {
arrUserPassword = pdfParams.getUserPassword().getBytes();
}
if (StringUtils.isNotBlank(pdfParams.getOwnerPassword())) {
arrOwnerPassword = pdfParams.getOwnerPassword().getBytes();
}
if (StringUtils.isNotBlank(pdfParams.getUserPassword()) || StringUtils.isNotBlank(pdfParams.getOwnerPassword())) {
stamper.setEncryption(arrUserPassword, arrOwnerPassword, PdfWriter.ALLOW_PRINTING, false);
}
//设置字体
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
// 获取总页数 +1, 下面从1开始遍历
int total = reader.getNumberOfPages() + 1;
PdfContentByte under;
for (int i = 1; i < total; i++) {
// 在内容上方加水印
under = stamper.getOverContent(i);
// 在内容下方加水印
//under = stamper.getUnderContent(i);
under.saveState();
under.beginText();
under.setFontAndSize(baseFont, fontSize);
//文字加粗
//设置文本描边宽度
//under.setLineWidth(0.3);
//设置文本为描边模式, 会导致 setColorFill 颜色失效
//under.setTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE);
//字体颜色
under.setColorFill(fontColor);
// 设置透明度
PdfGState gs = new PdfGState();
gs.setFillOpacity(pdfParams.getFillOpacity());
under.setGState(gs);
//水印字体和大小
Rectangle pageRect = reader.getPageSizeWithRotation(i);
int width1 = (int) pageRect.getWidth();
int height1 = (int) pageRect.getHeight();
//fontSize = (width1 + height1) / pdfParams.getDefaultFontSize();
x = (float) (width1) / 2;
y = (float) height1 / 2;
// 将分段的字段进行输出编写
for (int z = 0; z < waterMarkContents.length; z++) {
//文字
String itemWaterMark = waterMarkContents[z];
// 间隔距离(参数可调节)
int interval = fontSize * z;
under.showTextAligned(Element.ALIGN_CENTER, itemWaterMark, x, y - (interval + textH * z), angle);
}
// 添加水印文字
under.endText();
}
stamper.close();
reader.close();
//outputStream 转换为 byte
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
outputStream.writeTo(byteArrayOutputStream);
byteArray = byteArrayOutputStream.toByteArray();
log.info("{}结束调用,返回结果:{}", methodName, "OK");
} catch (Exception e) {
log.error("{}调用异常 >> 入参:【pdfParams = {}】,e:", methodName, pdfParams, e);
}
return byteArray;
}
}
测试代码及结果
参考:测试代码及结果