本文使用jar包pom.xml

<!--水印相关   start-->
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itext-asian</artifactId>
			<version>5.2.0</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itextpdf</artifactId>
			<version>5.4.3</version>
		</dependency>
		<dependency>
			<groupId>com.lowagie</groupId>
			<artifactId>itext</artifactId>
			<version>2.1.7</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.17</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.17</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.17</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>ooxml-schemas</artifactId>
			<version>1.0</version>
		</dependency>

		<!-- word -->
		<dependency>
			<groupId>e-iceblue</groupId>
			<artifactId>spire.doc.free</artifactId>
			<version>5.2.0</version>
		</dependency>
		<!-- excel  -->
		<dependency>
			<groupId>e-iceblue</groupId>
			<artifactId>spire.xls.free</artifactId>
			<version>5.1.0</version>
		</dependency>
		<dependency>
			<groupId>e-iceblue</groupId>
			<artifactId>spire.pdf.free</artifactId>
			<version>5.1.0</version>
		</dependency>
		<!-- ppt -->
		<dependency>
			<groupId>e-iceblue</groupId>
			<artifactId>spire.presentation.free</artifactId>
			<version>5.1.0</version>
		</dependency>

office 相关格式文档的加密主要使用微软提供的Spire.Office for Java ,free部分有针对性每个类型的API说明和示例,请自行参考以下链接。下面也会附上我在项目中的实际工具类。

Spire.Office for Java | 专业的 Java Office 套件 | 创建、修改、转换、打印 Word/PowerPoint/PDF 文档

我的策略是读取原文件,加水印后写入新的文件。工具类三个参数依次为原文件路劲、水印文件路径、水印文字内容。下面详细分解。

public static void main(String[] args) throws IOException {
        String markText = "cq-tengk "+new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String oldFile = "D:/tmp/tmp/test.doc";
        String newFile = "D:/tmp/res/test.doc";
        addWordWaterMark(oldFile,newFile,markText);
//        setWordWaterMark(oldFile,newFile,markText);
//        addWaterMark(oldFile,newFile,markText);
//        makeWaterMark(oldFile,newFile,markText);
    }

PDF加水印

/**
     *pdf文件添加文字水印
     *
     * @param input         原PDF位置
     * @param output        输出文件的位置
     * @param waterMarkName 页脚添加水印
     */
    public static void addPDFWaterMark(String input, String output, String waterMarkName) {
        BufferedOutputStream bos = null;
        try {
            bos = new BufferedOutputStream(new FileOutputStream(new File(output)));
            com.itextpdf.text.pdf.PdfReader reader = new com.itextpdf.text.pdf.PdfReader(input);
            com.itextpdf.text.pdf.PdfStamper stamper = new com.itextpdf.text.pdf.PdfStamper(reader, bos);

            // 获取总页数 +1, 下面从1开始遍历
            int total = reader.getNumberOfPages() + 1;
            // 使用classpath下面的字体库
            com.itextpdf.text.pdf.BaseFont base = null;
            try {
                base = com.itextpdf.text.pdf.BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", com.itextpdf.text.pdf.BaseFont.EMBEDDED);
            } catch (Exception e) {
                // 日志处理
                e.printStackTrace();
            }

            // 间隔
            int interval = -15;
            // 获取水印文字的高度和宽度
            int textH = 0, textW = 0;
            JLabel label = new JLabel();
            label.setText(waterMarkName);
            FontMetrics metrics = label.getFontMetrics(label.getFont());
            textH = metrics.getHeight();
            textW = metrics.stringWidth(label.getText());
            System.out.println("textH: " + textH);
            System.out.println("textW: " + textW);

            // 设置水印透明度
            com.itextpdf.text.pdf.PdfGState gs = new com.itextpdf.text.pdf.PdfGState();
            gs.setFillOpacity(0.2f);
            gs.setStrokeOpacity(0.7f);

            com.itextpdf.text.Rectangle pageSizeWithRotation = null;
            PdfContentByte content = null;
            for (int i = 1; i < total; i++) {
                // 在内容上方加水印
                content = stamper.getOverContent(i);
                // 在内容下方加水印
                // content = stamper.getUnderContent(i);
                content.saveState();
                content.setGState(gs);

                // 设置字体和字体大小
                content.beginText();
                content.setFontAndSize(base, 20);

                // 获取每一页的高度、宽度
                pageSizeWithRotation = reader.getPageSizeWithRotation(i);
                float pageHeight = pageSizeWithRotation.getHeight();
                float pageWidth = pageSizeWithRotation.getWidth();

                // 根据纸张大小多次添加, 水印文字成30度角倾斜
                for (int height = interval + textH; height < pageHeight; height = height + textH * 6) {
                    for (int width = interval + textW; width < pageWidth + textW; width = width + textW * 2) {
                        content.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, 30);
                    }
                }

                content.endText();
            }

            // 关流
            stamper.close();
            reader.close();
        } catch (FileNotFoundException e) {
            log.error("PDF加水印失败",e);
            throw new RuntimeException("PDF makewater fail:生成ppt文件失败");
        } catch (DocumentException e) {
            log.error("PDF加水印失败",e);
            throw new RuntimeException("PDF makewater fail:生成ppt文件失败");
        } catch (IOException e) {
            log.error("PDF加水印失败",e);
            throw new RuntimeException("PDF makewater fail:生成ppt文件失败");
        }

    }

Word水印   支持doc和docx

/**
     * word文字水印
     *
     * @param inputPath
     * @param outPath
     * @param markStr
     */
    public static void addWordWaterMark(String inputPath, String outPath, String markStr) {
        //加载示例文档
        Document doc = new Document();
        doc.loadFromFile(inputPath);
        //添加艺术字并设置大小
        ShapeObject shape = new ShapeObject(doc, ShapeType.Text_Plain_Text);
        shape.setWidth(80);
        shape.setHeight(20);
        //设置艺术字文本内容、位置及样式
        shape.setVerticalPosition(30);
        shape.setHorizontalPosition(20);
        shape.setRotation(315);
        shape.getWordArt().setFontFamily("宋体");
        shape.getWordArt().setText(markStr);
        shape.setFillColor(Color.red);
        shape.setLineStyle(ShapeLineStyle.Single);
        shape.setStrokeColor(new Color(192, 192, 192, 255));
        shape.setStrokeWeight(1);

        Section section;
        HeaderFooter header;
        for (int n = 0; n < doc.getSections().getCount(); n++) {
            section = doc.getSections().get(n);
            //获取section的页眉
            header = section.getHeadersFooters().getHeader();
            Paragraph paragraph;

            if (header.getParagraphs().getCount() > 0) {
                //如果页眉有段落,取它第一个段落
                paragraph = header.getParagraphs().get(0);
            } else {
                //否则新增加一个段落到页眉
                paragraph = header.addParagraph();
            }
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 3; j++) {
                    //复制艺术字并设置多行多列位置
                    shape = (ShapeObject) shape.deepClone();
                    shape.setVerticalPosition(50 + 150 * i);
                    shape.setHorizontalPosition(20 + 160 * j);
                    paragraph.getChildObjects().add(shape);
                }
            }
        }
        //保存文档
        doc.saveToFile(outPath, FileFormat.Docx_2013);
    }

Excel     xlsx格式

/**
     * excel添加水印
     *
     * @param inputSrc      原始文件路径
     * @param outputSrc     生成文件路径
     * @param waterMarkName 水印内容
     */
    private static void addExcelWaterMark(String inputSrc, String outputSrc, String waterMarkName) {
        byte[] fileData = OfficeWaterMarkUtil.getBytesByFile(inputSrc);
        BufferedImage image = createWaterMarkImage(waterMarkName);
        // 导出到字节流B
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", os);
            InputStream sbs = new ByteArrayInputStream(fileData);
            XSSFWorkbook workbook = new XSSFWorkbook(sbs);
            int pictureIdx = workbook.addPicture(os.toByteArray(), Workbook.PICTURE_TYPE_PNG);
            POIXMLDocumentPart poixmlDocumentPart = workbook.getAllPictures().get(pictureIdx);

            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {//获取每个Sheet表
                XSSFSheet sheet = workbook.getSheetAt(i);
                PackagePartName ppn = poixmlDocumentPart.getPackagePart().getPartName();
                String relType = XSSFRelation.IMAGES.getRelation();
                PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null);
                sheet.getCTWorksheet().addNewPicture().setId(pr.getId());
            }
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                workbook.write(bos);
            } finally {
                bos.close();
            }
            bos.writeTo(new BufferedOutputStream(new FileOutputStream(outputSrc)));
        } catch (IOException e) {
            log.error("Excel加水印失败",e);
            throw new RuntimeException("excel makewater fail:生成ppt文件失败");
        }

    }

Excel  xls格式

package com.liukuquanshu.thirdparty.util;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Font;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Excel 加水印工具类   支持xls和xlsx
 * @author tkai
 */
public class ExcelWaterMarkUtil {

    public static void main(String[] args) {
        String markText = "cq-tengk "+new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String oldFile = "D:/tmp/tmp/数科_软件著作权清单.xls";
        String newFile = "D:/tmp/res/数科_软件著作权清单.xls";

        setExcelWaterMark(oldFile,newFile,markText);

    }




    /**
     *
     * @param wb   Excel Workbook
     * @param sheet  需要打水印的Excel
     * @param waterRemark  水印文字
     * @param startXCol   水印起始列
     * @param startYRow  水印起始行
     * @param betweenXCol  水印横向之间间隔多少列
     * @param betweenYRow  水印纵向之间间隔多少行
     * @param XCount    横向共有水印多少个
     * @param YCount    纵向共有水印多少个
     * @param waterRemarkWidth   水印图片宽度为多少列
     * @param waterRemarkHeight   水印图片高度为多少行
     * @throws IOException
     */
    public static void putWaterRemarkToExcel(Workbook wb, Sheet sheet, String waterRemark, int startXCol,
                                             int startYRow, int betweenXCol, int betweenYRow, int XCount, int YCount, int waterRemarkWidth,
                                             int waterRemarkHeight) throws IOException {

        // 加载图片
        ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
        BufferedImage bufferImg = createWaterMarkImage(waterRemark);
        ImageIO.write(bufferImg, "png", byteArrayOut);
        // 开始打水印
        Drawing drawing = sheet.createDrawingPatriarch();
        Drawing<?> drawingPatriarch = sheet.getDrawingPatriarch();
        // 按照共需打印多少行水印进行循环
        for (int yCount = 0; yCount < YCount; yCount++) {
            // 按照每行需要打印多少个水印进行循环
            for (int xCount = 0; xCount < XCount; xCount++) {
                // 创建水印图片位置
                int xIndexInteger = startXCol + (xCount * waterRemarkWidth) + (xCount * betweenXCol);
                int yIndexInteger = startYRow + (yCount * waterRemarkHeight) + (yCount * betweenYRow);
                /*
                 * 参数定义: 第一个参数是(x轴的开始节点); 第二个参数是(是y轴的开始节点); 第三个参数是(是x轴的结束节点);
                 * 第四个参数是(是y轴的结束节点); 第五个参数是(是从Excel的第几列开始插入图片,从0开始计数);
                 * 第六个参数是(是从excel的第几行开始插入图片,从0开始计数); 第七个参数是(图片宽度,共多少列);
                 * 第8个参数是(图片高度,共多少行);
                 */
                ClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, xIndexInteger,
                        yIndexInteger, xIndexInteger + waterRemarkWidth, yIndexInteger + waterRemarkHeight);

                Picture pic = drawing.createPicture(anchor,
                        wb.addPicture(byteArrayOut.toByteArray(), Workbook.PICTURE_TYPE_PNG));
                pic.resize();
            }
        }
    }

    public static void setExcelWaterMark(String inputSrc, String outputSrc, String waterMarkName){
        try {
            //读取excel文件
            Workbook wb =null;
            if (inputSrc.endsWith("xls")) {
                wb = new HSSFWorkbook(new FileInputStream(inputSrc));
            }else if (inputSrc.endsWith("xlsx")){
                wb = new XSSFWorkbook(new FileInputStream(inputSrc));
            }
            //获取excel sheet个数
            int sheets = wb.getNumberOfSheets();
            //循环sheet给每个sheet添加水印
            for (int i = 0; i < sheets; i++) {
                Sheet sheet = wb.getSheetAt(i);
                //获取excel实际所占行
                int row = sheet.getFirstRowNum() + sheet.getLastRowNum();
                //获取excel实际所占列
                Row row1 = sheet.getRow(sheet.getFirstRowNum());
                if (row1==null){
                    continue;
                }
                int cell = sheet.getRow(sheet.getFirstRowNum()).getLastCellNum() + 1;
                //根据行与列计算实际所需多少水印
                putWaterRemarkToExcel(wb, sheet, waterMarkName, 0, 0, 6, 8, cell / 6 + 1, row / 8 + 1, 0, 0);

                //设置为受保护
                sheet.protectSheet(waterMarkName);
            }
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            try {
                wb.write(os);
            } catch (IOException e) {
                e.printStackTrace();
            }
            wb.close();
            byte[] content = os.toByteArray();
            // Excel文件生成后存储的位置。
            File file1 = new File(outputSrc);
            OutputStream fos = null;
            try {
                fos = new FileOutputStream(file1);
                fos.write(content);
                os.close();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }



    public static BufferedImage createWaterMarkImage(String waterMark) {
        String[] textArray = waterMark.split("\n");
        Font font = new Font("microsoft-yahei", Font.PLAIN, 20);
        Integer width = 500;
        Integer height = 200;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        // 背景透明 开始
        Graphics2D g = image.createGraphics();
        image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g.dispose();
        // 背景透明 结束
        g = image.createGraphics();
        g.setColor(new Color(Integer.parseInt("#C5CBCF".substring(1), 16)));// 设定画笔颜色
        g.setFont(font);// 设置画笔字体
        g.shear(0.1, -0.26);// 设定倾斜度
        // 设置字体平滑
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        int y = 150;
        for (int i = 0; i < textArray.length; i++) {
            g.drawString(textArray[i], 0, y);// 画出字符串
            y = y + font.getSize();
        }
        g.dispose();// 释放画笔
        return image;
    }



}

图片水印   jpg  png 格式

package com.liukuquanshu.thirdparty.util;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 * Description: 图片水印工具类
 * @author tengk
 * @version 1.0
 */
@Slf4j
public class ImgWaterMarkUtil {

    // 水印透明度
    private static float alpha = 0.7f;
    // 水印横向位置
    private static int positionWidth = 150;
    // 水印纵向位置
    private static int positionHeight = 300;
    // 水印文字字体
    private static Font font = new Font("宋体", Font.BOLD, 20);
    // 水印文字颜色
    private static Color color = Color.white;

    //文字水印位置铺满全屏
    private static ArrayList position1;
    private static ArrayList position2;

    /**
     *
     * @param alpha
     *            水印透明度
     * @param positionWidth
     *            水印横向位置
     * @param positionHeight
     *            水印纵向位置
     * @param font
     *            水印文字字体
     * @param color
     *            水印文字颜色
     */
    public static void setImageMarkOptions(float alpha, int positionWidth,
                                           int positionHeight, Font font, Color color) {
        if (alpha != 0.0f) {
            ImgWaterMarkUtil.alpha = alpha;
        }
        if (positionWidth != 0) {
            ImgWaterMarkUtil.positionWidth = positionWidth;
        }
        if (positionHeight != 0) {
            ImgWaterMarkUtil.positionHeight = positionHeight;
        }
        if (font != null) {
            ImgWaterMarkUtil.font = font;
        }
        if (color != null) {
            ImgWaterMarkUtil.color = color;
        }
    }

    /**
     * 给图片添加水印图片
     *
     * @param iconPath
     *            水印图片路径
     * @param srcImgPath
     *            源图片路径
     * @param targerPath
     *            目标图片路径
     */
    public static void markImageByIcon(String iconPath, String srcImgPath,
                                       String targerPath) {
        markImageByIcon(iconPath, srcImgPath, targerPath, null);
    }

    /**
     * 给图片添加水印图片、可设置水印图片旋转角度
     *
     * @param iconPath
     *            水印图片路径
     * @param srcImgPath
     *            源图片路径
     * @param targerPath
     *            目标图片路径
     * @param degree
     *            水印图片旋转角度
     */
    public static void markImageByIcon(String iconPath, String srcImgPath,
                                       String targerPath, Integer degree) {
        OutputStream os = null;
        try {

            Image srcImg = ImageIO.read(new File(srcImgPath));

            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
                    srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);

            // 1、得到画笔对象
            Graphics2D g = buffImg.createGraphics();

            // 2、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);

            g.drawImage(
                    srcImg.getScaledInstance(srcImg.getWidth(null),
                            srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,
                    null);
            // 3、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree),
                        (double) buffImg.getWidth() / 2,
                        (double) buffImg.getHeight() / 2);
            }

            // 4、水印图片的路径 水印图片一般为gif或者png的,这样可设置透明度
            ImageIcon imgIcon = new ImageIcon(iconPath);

            // 5、得到Image对象。
            Image img = imgIcon.getImage();

            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
                    alpha));

            // 6、水印图片的位置
            g.drawImage(img, positionWidth, positionHeight, null);
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
            // 7、释放资源
            g.dispose();

            // 8、生成图片
            os = new FileOutputStream(targerPath);
            ImageIO.write(buffImg, "JPG", os);

            System.out.println("图片完成添加水印图片");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(null != os) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 给图片添加水印文字
     *
     * @param logoText
     *            水印文字
     * @param srcImgPath
     *            源图片路径
     * @param targerPath
     *            目标图片路径
     */
    public static void markImageByText(String logoText, String srcImgPath,
                                       String targerPath,int allFlag) {
        markImageByText(logoText, srcImgPath, targerPath, null,allFlag);
    }

    /**
     * 给图片添加水印文字、可设置水印文字的旋转角度
     *
     * @param logoText
     * @param srcImgPath
     * @param targerPath
     * @param degree
     */
    public static void markImageByText(String logoText, String srcImgPath,
                                       String targerPath, Integer degree,int allFlag) {

        InputStream is = null;
        OutputStream os = null;
        try {
            // 1、源图片
            Image srcImg = ImageIO.read(new File(srcImgPath));
            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
                    srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);

            // 2、得到画笔对象
            Graphics2D g = buffImg.createGraphics();
            // 3、设置对线段的锯齿状边缘处理
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(
                    srcImg.getScaledInstance(srcImg.getWidth(null),
                            srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,
                    null);
            // 4、设置水印旋转
            if (null != degree) {
                g.rotate(Math.toRadians(degree),
                        (double) buffImg.getWidth() / 2,
                        (double) buffImg.getHeight() / 2);
            }
            // 5、设置水印文字颜色
            g.setColor(color);
            // 6、设置水印文字Font
            g.setFont(font);
            // 7、设置水印文字透明度
            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
                    alpha));
            // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y)
            if (allFlag == 1){
                int width = srcImg.getWidth(null);
                int height = srcImg.getHeight(null);
                position1 = new ArrayList();
                position2 = new ArrayList();
                position1.add(0);
                position1.add(width/4);
                position1.add(width/2);
                position1.add(width*3/4);
                position1.add(width);
                position2.add(0);
                position2.add(height/4);
                position2.add(height/2);
                position2.add(height*3/4);
                position2.add(height);

                for (int i = 0; i < position1.size(); i++) {
                    for (int j = 0; j < position2.size(); j++) {
                        g.drawString(logoText,(Integer) position1.get(i),(Integer) position2.get(j));
                    }
                }
            }else {
                g.drawString(logoText,positionWidth,positionHeight);
            }

            // 9、释放资源
            g.dispose();
            // 10、生成图片
            os = new FileOutputStream(targerPath);
            ImageIO.write(buffImg, "JPG", os);

            System.out.println("图片完成添加水印文字");

        } catch (Exception e) {
            log.error("图片加水印失败",e);
            throw new RuntimeException("图片加水印失败");
        } finally {
            try {
                if (null == is) {
                } else {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                if (null != os) {
                    os.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {

        String markText = "cq-tengk "+new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        //图片测试
        /*String srcImgPath = "D:/tmp/tmp/31.jpg";
        String targerTextPath2 = "D:/tmp/res/3000.jpg";
        String targerTextPath = "D:/tmp/tmp/3000.jpg";
        // 给图片添加水印文字
        markImageByText(markText, srcImgPath, targerTextPath,0);
        // 给图片添加水印文字,水印文字旋转-45
        markImageByText(markText, srcImgPath, targerTextPath2, -45,1);*/

        //文件测试
//        String oldFile = "D:/tmp/tmp/20A00053公开招标(定稿).doc";
//        String newFile = "D:/tmp/res/20A00053公开招标(定稿).doc";
//        String oldFile = "D:/tmp/tmp/5G专网产品资费设计.docx";
//        String newFile = "D:/tmp/res/5G专网产品资费设计.docx";
//        String oldFile = "D:/tmp/tmp/2.xlsx";
//        String newFile = "D:/tmp/res/22.xlsx";
        String oldFile = "D:/tmp/tmp/2.pdf";
        String newFile = "D:/tmp/res/22.pdf";
//        String oldFile = "D:/tmp/tmp/2.pptx";
//        String newFile = "D:/tmp/res/2.pptx";
        OfficeWaterMarkUtil.addWaterMarkOffice(oldFile,newFile,markText);

    }

}

PPTX格式

package com.liukuquanshu.thirdparty.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.poi.sl.usermodel.PictureData;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureShape;
import org.apache.poi.xslf.usermodel.XSLFSlide;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author tkai
 * @description: TODO
 * @date 2022/9/28 17:12
 */
@Slf4j
public class PPTWaterMarkUtil {


    public static void main(String[] args) {
        String markText = "cq-tengk "+new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String oldFile = "D:/tmp/tmp/托尔斯泰.ppt";
        String newFile = "D:/tmp/res/托尔斯泰.ppt";
        setPPTWaterMark(oldFile,newFile,markText);



    }


    /**
     * PPT设置水印
     *
     * @param path
     * @param targetpath
     * @param markStr
     * @throws IOException
     */
    public static void setPPTWaterMark(String path, String targetpath, String markStr) {
        XMLSlideShow slideShow = null;
        try {
            slideShow = new XMLSlideShow(new FileInputStream(path));
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:", e);
            throw new RuntimeException("setPPTWaterMark fail:获取PPT文件失败");
        }
        ByteArrayOutputStream os = null;
        FileOutputStream out = null;
        try {
            //获取水印
            os = getImage(markStr);
            PictureData pictureData1 = slideShow.addPicture(os.toByteArray(), PictureType.PNG);
            for (XSLFSlide slide : slideShow.getSlides()) {
                XSLFPictureShape pictureShape = slide.createPicture(pictureData1);
//                pictureShape.setAnchor(new java.awt.Rectangle(250, 0, 500, 500));
                pictureShape.setAnchor(pictureShape.getAnchor());
            }
            out = new FileOutputStream(targetpath);
            slideShow.write(out);
        } catch (IOException e) {
            log.error("setPPTWaterMark fail:" + e);
            throw new RuntimeException("setPPTWaterMark 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();
                }
            }
        }
    }


    /**
     * 获取水印文字图片流
     *
     * @param text
     * @return
     */
    private static ByteArrayOutputStream getImage(String text) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            // 导出到字节流B
            BufferedImage image = createWaterMarkImageBig(text);
            ImageIO.write(image, "png", os);
        } catch (IOException e) {
//            log.error("getImage fail: 创建水印图片IO异常", e);
//            throw new MyException(ResultCode.FAILURE, "getImage fail: 创建水印图片IO异常");
        }
        return os;
    }

    /**
     * 根据文字生成水印图片(大号 平铺)
     *
     * @param text
     * @return
     */
    public static BufferedImage createWaterMarkImageBig(String text) {
        Integer width = 1000;
        Integer height = 800;
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 获取bufferedImage对象
        Font font = new Font("宋体", Font.PLAIN, 70);
        Graphics2D g2d = image.createGraphics();
        image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
        g2d.dispose();
        g2d = image.createGraphics();
        //设置字体颜色和透明度
        g2d.setColor(new Color(0, 0, 0, 60));
        //设置字体
        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;
    }

}

因为spire free这一套使用有限制,比如ppt只能对十页以内加水印,十页以后的内容会被删去,所以使用了一些别的方法,参考出处因为反复改动记录不详,感谢前面的探索者,这里就不一一列出了。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐