itextpdf接口文档:
itextpdf添加水印代码:
<!-- PDF文件依赖包 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.1</version>
</dependency>
<!-- PDF文件字体 防止中文乱码 -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
package com.rliz.pdf;
import com.itextpdf.text.Element;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import java.io.FileOutputStream;
/**
* @Description: PDF增加水印工具类
*/
public class PDFAddWatermarkUtil {
/**
* 给PDF添加水印
* @param inputFilePath 原文件路径+名称,例如D:\\pdf\\test.pdf
* @param outputFilePath 添加水印后输出文件保存的路径+名称
* @param waterMarkContent 添加水印的内容
*/
public static void pdfAddWaterMark(String inputFilePath, String outputFilePath, String waterMarkContent) {
try {
// 水印的高和宽
int waterMarkHeight = 30;
int watermarkWeight = 60;
// 水印间隔距离
int waterMarkInterval = 100;
// 读取PDF文件流
PdfReader pdfReader = new PdfReader(inputFilePath);
// 创建PDF文件的模板,可以对模板的内容修改,重新生成新PDF文件
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(outputFilePath));
// 设置水印字体
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
// 设置PDF内容的Graphic State 图形状态
PdfGState pdfGraPhicState = new PdfGState();
// 填充透明度
pdfGraPhicState.setFillOpacity(0.2f);
// 轮廓不透明度
pdfGraPhicState.setStrokeOpacity(0.4f);
// PDF页数
int pdfPageNum = pdfReader.getNumberOfPages() + 1;
// PDF文件内容字节
PdfContentByte pdfContent;
// PDF页面矩形区域
Rectangle pageRectangle;
for (int i = 1; i < pdfPageNum; i++) {
// 获取当前页面矩形区域
pageRectangle = pdfReader.getPageSizeWithRotation(i);
// 获取当前页内容,getOverContent表示之后会在页面内容的上方加水印
pdfContent = pdfStamper.getOverContent(i);
// 获取当前页内容,getOverContent表示之后会在页面内容的下方加水印
// pdfContent = pdfStamper.getUnderContent(i);
pdfContent.saveState();
// 设置水印透明度
pdfContent.setGState(pdfGraPhicState);
// 开启写入文本
pdfContent.beginText();
// 设置字体
pdfContent.setFontAndSize(baseFont, 20);
// 在高度和宽度维度每隔waterMarkInterval距离添加一个水印
for (int height = waterMarkHeight; height < pageRectangle.getHeight(); height = height + waterMarkInterval) {
for (int width = watermarkWeight; width < pageRectangle.getWidth() + watermarkWeight;
width = width + waterMarkInterval) {
// 添加水印文字并旋转30度角
pdfContent.showTextAligned(Element.ALIGN_LEFT, waterMarkContent, width - watermarkWeight,
height - waterMarkHeight, 30);
}
}
// 停止写入文本
pdfContent.endText();
}
pdfStamper.close();
pdfReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
// 20230420 10_46_29--33.pdf
// 20220711 11_04_38--29.pdf
String fileName = "1";
pdfAddWaterMark("D:\\pdf\\" + fileName +".pdf", "D:\\pdf\\"+fileName + "-" + System.currentTimeMillis()+"-watermark.pdf","20230426170633");
} catch (Exception e) {
e.printStackTrace();
}
}
}
效果如下:
如果出现水印被遮挡或PDF内容被遮挡可通过以下代码调整:
// 获取当前页内容,getOverContent表示之后会在页面内容的上方加水印
pdfContent = pdfStamper.getOverContent(i);
// 获取当前页内容,getOverContent表示之后会在页面内容的下方加水印
// pdfContent = pdfStamper.getUnderContent(i);
为什么pdfStamper.getOverContent()和pdfStamper.getUnderContent()能做到在页面内容之前或之后添加内容?
可以看到PdfStamper中这两个方法完全一样:
不同的地方在于pdfStamperImpl分别将页面模板内容赋值给了under和over属性,这两个属性控制添加内容在原始内容(ps)的上层还是下层。
pdfStamperImpl内部类: