Java 实现 文档 添加 水印 工具类
2023-12-14 21:23:06
一、pom 文件引用
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.0</version>
<exclusions>
<!--解决含嵌入文件ppt转换报错 ArrayStoreException-->
<exclusion>
<artifactId>xmlbeans</artifactId>
<groupId>org.apache.xmlbeans</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.16</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
二、代码展示
2.1,ImageUtil 图片工具类
package cn.piesat.space.watermark.util;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
/**
* @author: wangjing
* @createTime: 2023-12-05 15:01
* @version: 1.0.0
* @Description: 图片工具类
*/
public class ImageUtil {
/**
* 调整图片尺寸
*
* @param inputPath 原图片地址
* @param outPath 新图片地址
* @param newWidth 新图片宽
* @param newHeight 新图片高
*/
public static void resizeImage(String inputPath, String outPath, Integer newWidth, Integer newHeight) {
try {
BufferedImage bufferedImage = readPicture(inputPath);
// 创建新的 BufferedImage,并设置绘制质量
BufferedImage resizedImage = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = resizedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
// 绘制原始图像到新的 BufferedImage,并进行缩放
Image scaledImage = bufferedImage.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH);
g2d.drawImage(scaledImage, 0, 0, null);
g2d.dispose();
// 保存新的图片
ImageIO.write(resizedImage, "jpg", new File(outPath));
System.out.println("图片尺寸调整完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 读取图片
*
* @param path
* @return
*/
public static BufferedImage readPicture(String path) {
try {
// 尝试获取本地
return readLocalPicture(path);
} catch (Exception e) {
// 尝试获取网路
return readNetworkPicture(path);
}
}
/**
* 读取本地图片
*
* @param path
* @return
*/
public static BufferedImage readLocalPicture(String path) {
if (null == path) {
throw new RuntimeException("本地图片路径不能为空");
}
// 读取原图片信息 得到文件
File srcImgFile = new File(path);
try {
// 将文件对象转化为图片对象
return ImageIO.read(srcImgFile);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 读取网络图片
*
* @param path 网络图片地址
*/
public static BufferedImage readNetworkPicture(String path) {
if (null == path) {
throw new RuntimeException("网络图片路径不能为空");
}
try {
// 创建一个URL对象,获取网络图片的地址信息
URL url = new URL(path);
// 将URL对象输入流转化为图片对象 (url.openStream()方法,获得一个输入流)
BufferedImage bugImg = ImageIO.read(url.openStream());
if (null == bugImg) {
throw new RuntimeException("网络图片地址不正确");
}
return bugImg;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
2.1,DocumentWaterMarkUtils?文档水印工具类
package cn.piesat.space.watermark.util;
import cn.piesat.space.watermark.enums.WatermarkTypeEnum;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.*;
import com.microsoft.schemas.vml.CTShape;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlideMaster;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFHeader;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlObject;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.xml.namespace.QName;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.Field;
/**
* @author: wangjing
* @createTime: 2023-12-05 15:01
* @version: 1.0.0
* @Description: 文档水印工具类
*/
@Slf4j
public class DocumentWaterMarkUtils {
/**
* 水印默认字体
*/
private static Font defaultFont = new Font("宋体", Font.PLAIN, 70);
/**
* 水印默认字体颜色
*/
private static Color defaultColor = new Color(0, 0, 0, 60);
/**
* 水印透明度
*/
private static float alpha = 0.5f;
/**
* 水印之间的间隔
*/
private static final int xMove = 200;
/**
* 水印之间的间隔
*/
private static final int yMove = 200;
public static void main(String[] args) {
String watermarkText = "测试水印";
String watermarkImage = "/Users/wangjing/Desktop/watermark/test.jpeg";
// pdf
String pdfInputPath = "/Users/wangjing/Desktop/watermark/pdf/test.pdf";
String pdfOutPath = "/Users/wangjing/Desktop/watermark/pdf/test2.pdf";
addPdfWatermark(pdfInputPath, pdfOutPath, watermarkText);
// ppt
String pptInputPath = "/Users/wangjing/Desktop/watermark/ppt/test.pptx";
// excel 文字水印
String pptOutPath = "/Users/wangjing/Desktop/watermark/ppt/test2.pptx";
addPPTWatermark(pptInputPath, pptOutPath, 1, watermarkText, defaultFont, defaultColor);
// excel 图片水印
String pptOutPathImage = "/Users/wangjing/Desktop/watermark/ppt/test3.pptx";
addPPTWatermark(pptInputPath, pptOutPathImage, 2, watermarkImage, null, null);
// excel
String watermarkImageExcel = "/Users/wangjing/Desktop/watermark/image/test1.jpg";
String excelInputPath = "/Users/wangjing/Desktop/watermark/excel/test.xlsx";
// excel 文字水印
String excelOutPath = "/Users/wangjing/Desktop/watermark/excel/test2.xlsx";
addExcelWatermark(excelInputPath, excelOutPath, 1, watermarkText, defaultFont, defaultColor);
// excel 图片水印
String excelOutPathImage = "/Users/wangjing/Desktop/watermark/excel/test3.xlsx";
addExcelWatermark(excelInputPath, excelOutPathImage, 2, watermarkImageExcel, null, null);
//word 添加文字水印
String wordInputPath = "/Users/wangjing/Desktop/watermark/word/test.docx";
String wordOutPath = "/Users/wangjing/Desktop/watermark/word/test2.docx";
addWordWatermark(wordInputPath, wordOutPath, watermarkText, "#D3D3D3", true, false);
}
/**
* pdf设置文字水印
*
* @param inputPath
* @param outPath
* @param watermark
*/
public static void addPdfWatermark(String inputPath, String outPath, String watermark) {
// 创建输出文件
File file = new File(outPath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
log.error("addPdfWatermark fail: 创建输出文件IO异常", e);
throw new RuntimeException("addPdfWatermark fail: 创建输出文件IO异常");
}
}
BufferedOutputStream outBufferedOutputStream = null;
try {
outBufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
} catch (FileNotFoundException e) {
log.error("addPdfWatermark fail: 源文件不存在", e);
throw new RuntimeException("addPdfWatermark fail: 源文件不存在");
}
PdfStamper pdfStamper = null;
int total = 0;
PdfContentByte content;
com.itextpdf.text.Rectangle pageSizeWithRotation = null;
BaseFont base = null;
PdfReader inputPdfReader = null;
try {
inputPdfReader = new PdfReader(inputPath);
// 解决PdfReader not opened with owner password
Field f = PdfReader.class.getDeclaredField("ownerPasswordUsed");
f.setAccessible(true);
f.set(inputPdfReader, Boolean.TRUE);
pdfStamper = new PdfStamper(inputPdfReader, outBufferedOutputStream);
total = inputPdfReader.getNumberOfPages() + 1;
base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
} catch (IOException e) {
log.error("addPdfWatermark fail:", e);
throw new RuntimeException("addPdfWatermark fail:IOException");
} catch (DocumentException e) {
log.error("addPdfWatermark fail:", e);
throw new RuntimeException("addPdfWatermark fail: DocumentException");
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
// 获取水印文字的高度和宽度
Integer textH = 0;
Integer textW = 0;
JLabel label = new JLabel();
label.setText(watermark);
FontMetrics metrics = label.getFontMetrics(label.getFont());
textH = metrics.getHeight();
textW = metrics.stringWidth(label.getText());
PdfGState gs = new PdfGState();
for (Integer i = 1; i < total; i++) {
//在内容上方加水印
content = pdfStamper.getOverContent(i);
gs.setFillOpacity(alpha);
content.saveState();
content.setGState(gs);
content.beginText();
content.setFontAndSize(base, 20);
// 获取每一页的高度、宽度
pageSizeWithRotation = inputPdfReader.getPageSizeWithRotation(i);
float pageHeight = pageSizeWithRotation.getHeight();
float pageWidth = pageSizeWithRotation.getWidth();
// 根据纸张大小多次添加, 水印文字成30度角倾斜
for (int height = -5 + textH; height < pageHeight; height = height + yMove) {
for (int width = -5 + textW; width < pageWidth + textW; width = width + xMove) {
content.showTextAligned(Element.ALIGN_LEFT, watermark, width - textW, height - textH, 30);
}
}
content.endText();
}
// 管理所有流
try {
pdfStamper.close();
outBufferedOutputStream.flush();
outBufferedOutputStream.close();
inputPdfReader.close();
} catch (IOException e) {
log.error("addPdfWatermark fail:", e);
throw new RuntimeException("addPdfWatermark fail: 关闭流异常,IOException");
} catch (DocumentException e) {
log.error("addPdfWatermark fail:", e);
throw new RuntimeException("addPdfWatermark fail: 关闭流异常,DocumentException");
}
}
/**
* PPT 添加水印
*
* @param inputPath 原ppt地址
* @param targetpath 新ppt地址
* @param watermarkType 水印类型(1:文字水印;2:图片水印)
* @param watermark 水印
* @param font 字体
* @param color 颜色
*/
public static void addPPTWatermark(String inputPath, String targetpath, Integer watermarkType, String watermark,
Font font, Color color) {
XMLSlideShow slideShow = null;
try {
slideShow = new XMLSlideShow(new FileInputStream(inputPath));
} catch (IOException e) {
log.error("addPPTWatermark fail:", e);
throw new RuntimeException("addPPTWatermark fail: 获取PPT文件失败");
}
ByteArrayOutputStream os = null;
FileOutputStream out = null;
try {
//获取水印
os = getWatermarkImage(watermarkType, watermark, font, color, 1280, 720);
PictureData pictureData = slideShow.addPicture(os.toByteArray(), PictureData.PictureType.PNG);
for (XSLFSlideMaster xslfSlideMaster : slideShow.getSlideMasters()) {
XSLFPictureShape pictureShape = xslfSlideMaster.createPicture(pictureData);
// pictureShape.setAnchor(new java.awt.Rectangle(0, 0, -1 , -1));
pictureShape.setAnchor(pictureShape.getAnchor());
}
out = new FileOutputStream(targetpath);
slideShow.write(out);
} catch (IOException e) {
log.error("addPPTWatermark fail:" + e);
throw new RuntimeException("addPPTWatermark fail: 生成ppt文件失败");
} finally {
if (slideShow != null) {
try {
slideShow.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* excel 添加水印
*
* @param inputPath 原excel地址
* @param outPath 新excel地址
* @param watermarkType 水印类型:1:文本水印;2:图片水印;
* @param watermark 水印(文字或图片URL)
* @param font 字体
* @param color 颜色
*/
public static void addExcelWatermark(String inputPath, String outPath, Integer watermarkType, String watermark,
Font font, Color color) {
//读取excel文件
XSSFWorkbook workbook = null;
try {
workbook = new XSSFWorkbook(new FileInputStream(inputPath));
} catch (FileNotFoundException e) {
log.error("addExcelWaterMark fail: 源文件不存在", e);
throw new RuntimeException("addExcelWaterMark fail: 源文件不存在");
} catch (IOException e) {
log.error("addExcelWaterMark fail: 读取源文件IO异常", e);
throw new RuntimeException("addExcelWaterMark fail: 读取源文件IO异常");
}
OutputStream fos = null;
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
//获取水印
os = getWatermarkImage(watermarkType, watermark, font, color, 1000, 800);
int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
// 获取每个Sheet表
for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
XSSFSheet xssfSheet = workbook.getSheetAt(i);
String rID =
xssfSheet.addRelation(null, XSSFRelation.IMAGES, workbook.getAllPictures().get(pictureIdx)).getRelationship().getId();
xssfSheet.getCTWorksheet().addNewPicture().setId(rID);
}
// Excel文件生成后存储的位置。
File file = new File(outPath);
fos = new FileOutputStream(file);
workbook.write(fos);
} catch (Exception e) {
log.error("addExcelWaterMark fail: 创建输出文件IO异常", e);
throw new RuntimeException("addExcelWaterMark fail: 创建输出文件IO异常");
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* word 添加文字水印
*
* @param inputPath 原文件地址
* @param outPath 新文件地址
* @param watermark 水印文字
* @param watermarkColor 水印字体颜色
* @param incline 是否倾斜(true 倾斜,false 不倾斜)
* @param readable 是否设置仅可读(true 仅可读,false 可编辑)
*/
public static void addWordWatermark(String inputPath, String outPath, String watermark, String watermarkColor,
Boolean incline, Boolean readable) {
// 根据URL 获取 XWPFDocument 对象
XWPFDocument xwpfDocument = null;
try {
xwpfDocument = new XWPFDocument(new FileInputStream(new File(inputPath)));
} catch (FileNotFoundException fileNotFoundException) {
log.error("addWordWaterMark fail: ", fileNotFoundException);
throw new RuntimeException("addWordWaterMark fail: 源文件不存在");
} catch (IOException ioException) {
log.error("addWordWaterMark fail: ", ioException);
throw new RuntimeException("addWordWaterMark fail: 读取源文件IO异常");
} catch (Exception exception) {
log.error("addWordWaterMark fail: ", exception);
throw new RuntimeException("addWordWaterMark fail: 不支持的文档格式");
}
XWPFHeaderFooterPolicy headerFooterPolicy = xwpfDocument.getHeaderFooterPolicy();
if (headerFooterPolicy == null) {
//兼容处理
headerFooterPolicy = xwpfDocument.createHeaderFooterPolicy();
}
//调用API添加水印,效果不好为水平居中
headerFooterPolicy.createWatermark(watermark);
//处理后续文档更新水印逻辑
XWPFHeader xwpfHeader = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT);
XWPFParagraph xwpfParagraph = xwpfHeader.getParagraphArray(0);
//设置水印样式和位置,保持倾斜角度更好看和实用
xwpfParagraph.getCTP().newCursor();
XmlObject[] xmlobjects = xwpfParagraph.getCTP().getRArray(0).getPictArray(0).selectChildren(
new QName("urn:schemas-microsoft-com:vml", "shape"));
if (xmlobjects.length > 0) {
CTShape ctshape = (CTShape) xmlobjects[0];
// 水印字体颜色
ctshape.setFillcolor(watermarkColor);
// 水印是否倾斜
if (incline) {
ctshape.setStyle(ctshape.getStyle() + ";rotation:315");
}
}
// 设置文档只读
if (readable) {
xwpfDocument.enforceReadonlyProtection();
}
File file = new File(outPath);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
log.error("addWordWaterMark fail: 创建输出文件IO异常", e);
throw new RuntimeException("addWordWaterMark fail: 创建输出文件失败");
}
}
try {
xwpfDocument.write(new FileOutputStream(outPath));
} catch (FileNotFoundException e) {
log.error("addWordWaterMark fail: 输出文件不存在", e);
throw new RuntimeException("addWordWaterMark fail: 创建输出文件失败");
} catch (IOException e) {
log.error("addWordWaterMark fail: ", e);
throw new RuntimeException("addWordWaterMark fail");
} finally {
if (xwpfDocument != null) {
try {
xwpfDocument.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 获取水印图片文件流
*
* @param watermarkType 水印类型(1:文字水印;2:图片水印)
* @param watermark 水印
* @param font 字体
* @param color 颜色
* @param width 图片宽
* @param height 图片高
* @return
*/
private static ByteArrayOutputStream getWatermarkImage(Integer watermarkType, String watermark, Font font,
Color color, Integer width, Integer height) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
// 导出到字节流B
BufferedImage bufferedImage = null;
if (WatermarkTypeEnum.TEXT_WATERMARK.getCode().equals(watermarkType)) {
bufferedImage = createWaterMarkImageBig(watermark, font, color, width, height);
} else {
// 图片水印
bufferedImage = ImageUtil.readPicture(watermark);
}
ImageIO.write(bufferedImage, "png", os);
} catch (IOException e) {
log.error("testToImage fail: 创建水印图片IO异常", e);
throw new RuntimeException("testToImage fail: 创建水印图片IO异常");
}
return os;
}
/**
* 根据文字生成水印图片(大号 平铺)
*
* @param text 文本文字
* @param font 字体
* @param color 颜色
* @return
*/
public static BufferedImage createWaterMarkImageBig(String text, Font font, Color color, Integer width,
Integer height) {
// 获取bufferedImage对象
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
g2d.dispose();
g2d = image.createGraphics();
//设置字体颜色和透明度
g2d.setColor(color);
//设置字体
g2d.setStroke(new BasicStroke(1));
//设置字体类型 加粗 大小
g2d.setFont(font);
//设置倾斜度
g2d.rotate(Math.toRadians(-30), (double) image.getWidth() / 2, (double) image.getHeight() / 2);
FontRenderContext context = g2d.getFontRenderContext();
Rectangle2D bounds = font.getStringBounds(text, context);
double x = (width - bounds.getWidth()) / 2;
double y = (height - bounds.getHeight()) / 2;
double ascent = -bounds.getY();
double baseY = y + ascent;
//写入水印文字原定高度过小,所以累计写水印,增加高度
g2d.drawString(text, (int) x, (int) baseY);
//设置透明度
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
//释放对象
g2d.dispose();
return image;
}
}
三、效果展示
3.1,word 水印
3.2,excel 水印
3.2.1,文字水印
3.2.2,图片水印
3.3,ppt 水印
3.3.1,文字水印
3.3.2,图片水印
3.4,PDF 水印
注:以上内容仅提供参考和交流,请勿用于商业用途,如有侵权联系本人删除!
文章来源:https://blog.csdn.net/wang_jing_jing/article/details/134933999
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!