java实现pdf添加水印

引入依赖

java 复制代码
        <!-- PDF水印-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
        <!-- 中文字体 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

工具类 PDFUtil.java

java 复制代码
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.RandomUtil;
import com.itextpdf.text.Element;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.springframework.util.Assert;

import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

public class PDFUtil {

//    public static void pdfAddWaterMark(String inputFilePath, String outputFilePath, String waterMarkContent) {
//        try{
//            System.out.println("开始添加水印...");
//            PdfStamper pdfStamper = null;
//            PdfReader pdfReader = null;
//
//            try {
//                // 水印的高和宽
//                int waterMarkHeight = 30;
//                int watermarkWeight = 60;
//
//                // 水印间隔距离
//                int waterMarkInterval = 50;
//
//                // 读取PDF文件流
//                pdfReader = new PdfReader(inputFilePath);
//
//                // 创建PDF文件的模板,可以对模板的内容修改,重新生成新PDF文件
//                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.1f);
//                // 轮廓不透明度
//                pdfGraPhicState.setStrokeOpacity(0.1f);
//
//                // 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();
//
//                }
//
//                System.out.println("导出成功");
//            } catch (Exception e) {
//                e.printStackTrace();
//            }finally {
//                pdfStamper.close();
//                pdfReader.close();
//            }
//            pdfStamper.close();
//            pdfReader.close();
//
//        }catch (Exception e){
//            e.printStackTrace();
//
//        }
//
//
//    }


    public static Boolean pdfAddWaterMark(String inputFilePath, String outputFilePath, String waterMarkContent) {
        System.out.println("开始添加水印...");

        Boolean state = true;
        PdfStamper pdfStamper = null;
        PdfReader pdfReader = null;
        InputStream inputStream = null;

        try {
            // 水印的高和宽
            int waterMarkHeight = 30;
            int watermarkWeight = 60;

            // 水印间隔距离
            int waterMarkInterval = 50;

            // 使用流式读取 PDF 文件
            inputStream = new FileInputStream(inputFilePath);
            pdfReader = new PdfReader(inputStream);

            // 创建 PDF 文件的模板,可以对模板的内容修改,重新生成新 PDF 文件
            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.1f); // 填充透明度
            pdfGraPhicState.setStrokeOpacity(0.1f); // 轮廓不透明度

            // PDF 页数
            int pdfPageNum = pdfReader.getNumberOfPages();

            // 逐页处理 PDF 文件
            for (int i = 1; i <= pdfPageNum; i++) {
                // 获取当前页面矩形区域
                Rectangle pageRectangle = pdfReader.getPageSizeWithRotation(i);

                // 获取当前页内容,getOverContent 表示之后会在页面内容的上方加水印
                PdfContentByte pdfContent = pdfStamper.getOverContent(i);

                pdfContent.saveState();
                pdfContent.setGState(pdfGraPhicState); // 设置水印透明度

                // 开启写入文本
                pdfContent.beginText();
                pdfContent.setFontAndSize(baseFont, 20);

                // 在高度和宽度维度每隔 waterMarkInterval 距离添加一个水印
                for (int height = waterMarkHeight; height < pageRectangle.getHeight(); height += waterMarkInterval) {
                    for (int width = watermarkWeight; width < pageRectangle.getWidth() + watermarkWeight; width += waterMarkInterval) {
                        // 添加水印文字并旋转 30 度角
                        pdfContent.showTextAligned(Element.ALIGN_LEFT, waterMarkContent,
                            width - watermarkWeight,
                            height - waterMarkHeight,
                            30);
                    }
                }

                // 停止写入文本
                pdfContent.endText();
                pdfContent.restoreState();
            }

            System.out.println("水印添加完成,文件已保存至: " + outputFilePath);
        } catch (Exception e) {
            e.printStackTrace();
            state =  false;
        } finally {
            // 关闭资源
            if (pdfStamper != null) {
                try {
                    pdfStamper.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (pdfReader != null) {
                pdfReader.close();
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return state;
        }
    }

    public static byte[] pdfAddWaterMark(byte[] inputPdfBytes, String waterMarkContent) {
        System.out.println("开始添加水印...");

        PdfStamper pdfStamper = null;
        PdfReader pdfReader = null;
        ByteArrayInputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;

        try {
            int waterMarkHeight = 30;
            int watermarkWeight = 60;
            int waterMarkInterval = 50;

            inputStream = new ByteArrayInputStream(inputPdfBytes);
            pdfReader = new PdfReader(inputStream);

            outputStream = new ByteArrayOutputStream();
            pdfStamper = new PdfStamper(pdfReader, outputStream);

            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfGState pdfGraPhicState = new PdfGState();
            pdfGraPhicState.setFillOpacity(0.1f);
            pdfGraPhicState.setStrokeOpacity(0.1f);

            int pdfPageNum = pdfReader.getNumberOfPages();

            for (int i = 1; i <= pdfPageNum; i++) {
                Rectangle pageRectangle = pdfReader.getPageSizeWithRotation(i);
                PdfContentByte pdfContent = pdfStamper.getOverContent(i);

                pdfContent.saveState();
                pdfContent.setGState(pdfGraPhicState);
                pdfContent.beginText();
                pdfContent.setFontAndSize(baseFont, 20);

                for (int height = waterMarkHeight; height < pageRectangle.getHeight(); height += waterMarkInterval) {
                    for (int width = watermarkWeight; width < pageRectangle.getWidth() + watermarkWeight; width += waterMarkInterval) {
                        pdfContent.showTextAligned(Element.ALIGN_LEFT, waterMarkContent,
                            width - watermarkWeight,
                            height - waterMarkHeight,
                            30);
                    }
                }

                pdfContent.endText();
                pdfContent.restoreState();
            }

            pdfStamper.close();
            pdfStamper = null;

            byte[] result = outputStream.toByteArray();
            System.out.println("水印添加完成,输出大小: " + result.length + " bytes");
            return result;
        } catch (Exception e) {
            throw new RuntimeException("PDF水印添加失败", e);
        } finally {
            if (pdfStamper != null) {
                try {
                    pdfStamper.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (pdfReader != null) {
                pdfReader.close();
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 添加图片水印 - 简化版本(使用默认参数)
     * @param inputFilePath 输入PDF文件路径
     * @param outputFilePath 输出PDF文件路径
     * @param imageWaterMarkPath 水印图片路径
     * @return 是否成功
     */
    public static Boolean pdfAddImageWaterMark(String inputFilePath, String outputFilePath, String imageWaterMarkPath) {
        return pdfAddImageWaterMark(inputFilePath, outputFilePath, imageWaterMarkPath, 0.3f, 3f);
    }

    /**
     * 添加图片水印 - 简化版本(使用默认参数)
     * @param inputPdfBytes 输入PDF字节数组
     * @param imageWaterMarkBytes 水印图片字节数组
     * @return 添加水印后的PDF字节数组
     */
    public static byte[] pdfAddImageWaterMark(byte[] inputPdfBytes, byte[] imageWaterMarkBytes) {
        return pdfAddImageWaterMark(inputPdfBytes, imageWaterMarkBytes, 0.3f, 3f);
    }

    /**
     * 添加图片水印 - 文件路径方式
     * @param inputFilePath 输入PDF文件路径
     * @param outputFilePath 输出PDF文件路径
     * @param imageWaterMarkPath 水印图片路径
     * @param opacity 水印透明度 (0.0f - 1.0f)
     * @param scale 图片缩放比例 (0.0f - 1.0f)
     * @return 是否成功
     */
    public static Boolean pdfAddImageWaterMark(String inputFilePath, String outputFilePath,
                                               String imageWaterMarkPath, float opacity, float scale) {
        System.out.println("开始添加图片水印...");

        Boolean state = true;
        PdfStamper pdfStamper = null;
        PdfReader pdfReader = null;
        InputStream pdfInputStream = null;
        InputStream imageInputStream = null;

        try {
            // 水印间隔距离
            int waterMarkInterval = 50;

            // 使用流式读取 PDF 文件
            pdfInputStream = new FileInputStream(inputFilePath);
            pdfReader = new PdfReader(pdfInputStream);

            // 读取水印图片
            URL imageUrl = ResourceUtil.getResource("waterMark/waterMark.png");
            Assert.notNull(imageUrl, "水印图片不存在");
            Image waterMarkImage = Image.getInstance(imageUrl);


            // 设置图片缩放
            waterMarkImage.scalePercent(scale);

            waterMarkImage.setRotationDegrees(30f);

            // 获取图片实际尺寸
            float imageWidth = waterMarkImage.getScaledWidth();
            float imageHeight = waterMarkImage.getScaledHeight();

            // 创建 PDF 文件的模板
            pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(outputFilePath));

            // 设置 PDF 内容的 Graphic State 图形状态
            PdfGState pdfGraPhicState = new PdfGState();
            pdfGraPhicState.setFillOpacity(opacity); // 填充透明度
            pdfGraPhicState.setStrokeOpacity(opacity); // 轮廓不透明度


            // PDF 页数
            int pdfPageNum = pdfReader.getNumberOfPages();

            // 逐页处理 PDF 文件
            for (int i = 1; i <= pdfPageNum; i++) {
                // 获取当前页面矩形区域
                Rectangle pageRectangle = pdfReader.getPageSizeWithRotation(i);
                float pageWidth = pageRectangle.getWidth();
                float pageHeight = pageRectangle.getHeight();

                // 获取当前页内容
                PdfContentByte pdfContent = pdfStamper.getOverContent(i);

                pdfContent.saveState();
                pdfContent.setGState(pdfGraPhicState); // 设置水印透明度

                // 在高度和宽度维度每隔 waterMarkInterval 距离添加一个水印图片
                for (float height = imageHeight; height < pageHeight; height += waterMarkInterval + imageHeight) {
                    for (float width = imageWidth + RandomUtil.randomFloat(-50f, 50f); width < pageWidth + imageWidth; width += waterMarkInterval + RandomUtil.randomFloat(-50f,50f) + imageWidth) {
                        // 设置图片位置
                        waterMarkImage.setAbsolutePosition(
                                width - imageWidth,
                                height - imageHeight
                        );

                        // 添加图片到PDF内容
                        pdfContent.addImage(waterMarkImage);
                    }
                }

                pdfContent.restoreState();
            }

            System.out.println("图片水印添加完成,文件已保存至: " + outputFilePath);
        } catch (Exception e) {
            e.printStackTrace();
            state = false;
        } finally {
            // 关闭资源
            closeResources(pdfStamper, pdfReader, pdfInputStream, imageInputStream);
            return state;
        }
    }

    /**
     * 添加图片水印 - 字节数组方式
     * @param inputPdfBytes 输入PDF字节数组
     * @param imageWaterMarkBytes 水印图片字节数组
     * @param opacity 水印透明度 (0.0f - 1.0f)
     * @param scale 图片缩放比例 (0.0f - 1.0f)
     * @return 添加水印后的PDF字节数组
     */
    public static byte[] pdfAddImageWaterMark(byte[] inputPdfBytes, byte[] imageWaterMarkBytes,
                                              float opacity, float scale) {
        System.out.println("开始添加图片水印...");

        PdfStamper pdfStamper = null;
        PdfReader pdfReader = null;
        ByteArrayInputStream pdfInputStream = null;
        ByteArrayInputStream imageInputStream = null;
        ByteArrayOutputStream outputStream = null;

        try {
            // 水印间隔距离
            int waterMarkInterval = 100;

            pdfInputStream = new ByteArrayInputStream(inputPdfBytes);
            pdfReader = new PdfReader(pdfInputStream);

            // 读取水印图片
            imageInputStream = new ByteArrayInputStream(imageWaterMarkBytes);
            Image waterMarkImage = Image.getInstance(imageWaterMarkBytes);

            // 设置图片缩放
            waterMarkImage.scalePercent(scale * 100);

            // 获取图片实际尺寸
            float imageWidth = waterMarkImage.getScaledWidth();
            float imageHeight = waterMarkImage.getScaledHeight();

            outputStream = new ByteArrayOutputStream();
            pdfStamper = new PdfStamper(pdfReader, outputStream);

            // 设置 PDF 内容的 Graphic State 图形状态
            PdfGState pdfGraPhicState = new PdfGState();
            pdfGraPhicState.setFillOpacity(opacity);
            pdfGraPhicState.setStrokeOpacity(opacity);

            int pdfPageNum = pdfReader.getNumberOfPages();

            for (int i = 1; i <= pdfPageNum; i++) {
                Rectangle pageRectangle = pdfReader.getPageSizeWithRotation(i);
                float pageWidth = pageRectangle.getWidth();
                float pageHeight = pageRectangle.getHeight();

                PdfContentByte pdfContent = pdfStamper.getOverContent(i);

                pdfContent.saveState();
                pdfContent.setGState(pdfGraPhicState);

                // 在页面上平铺水印图片
                for (float height = imageHeight; height < pageHeight; height += waterMarkInterval + imageHeight) {
                    for (float width = imageWidth; width < pageWidth + imageWidth; width += waterMarkInterval + imageWidth) {
                        waterMarkImage.setAbsolutePosition(
                                width - imageWidth,
                                height - imageHeight
                        );
                        pdfContent.addImage(waterMarkImage);
                    }
                }

                pdfContent.restoreState();
            }

            pdfStamper.close();
            byte[] result = outputStream.toByteArray();
            System.out.println("图片水印添加完成,输出大小: " + result.length + " bytes");
            return result;
        } catch (Exception e) {
            throw new RuntimeException("PDF图片水印添加失败", e);
        } finally {
            closeResources(pdfStamper, pdfReader, pdfInputStream, imageInputStream);
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 公共资源关闭方法
     */
    private static void closeResources(PdfStamper stamper, PdfReader reader, InputStream... streams) {
        if (stamper != null) {
            try {
                stamper.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (reader != null) {
            reader.close();
        }
        for (InputStream stream : streams) {
            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

调用测试

java 复制代码
    /**
     * 获取水印文件
     * @return
     */
    @RequestMapping("/getMarkFile")
    public void getMarkFile(String JsonParams, HttpServletResponse response) throws Exception {
        String path1 = "D:\\WorkNote\\项目文件\\ADO供应链\\译文_供应商注册.pdf";
        String path2 = "C:\\Users\\mingyann\\Desktop\\测试文件\\水印文件.pdf";
        String path3 = "C:\\Users\\mingyann\\Desktop\\waterMark.png";
        // Boolean pdfAddWaterMark = PDFUtil.pdfAddWaterMark(path1, path2, "我是测试水印");
        Boolean pdfAddWaterMark = PDFUtil.pdfAddImageWaterMark(path1,path2, path3, 0.3f, 3f);
    }
相关推荐
不绝1912 小时前
延迟函数/协同程序
java·开发语言
摇滚侠2 小时前
登录认证,验证码实现逻辑
java·intellij-idea
老毛肚2 小时前
java juc 01 进程与线程
java·开发语言
1candobetter2 小时前
JAVA后端开发——反射机制在Spring业务开发中的实际应用
java·开发语言·spring
野犬寒鸦2 小时前
WebSocket协同编辑:高性能Disruptor架构揭秘及项目中的实战应用
java·开发语言·数据库·redis·后端
橙露2 小时前
排序算法可视化:用 Java 实现冒泡、快排与归并排序的对比分析
java·python·排序算法
靠沿2 小时前
【优选算法】专题二——滑动窗口
java·数据结构·算法
鸡蛋豆腐仙子2 小时前
redis及实现分布式锁的原理
java·redis·分布式·学习·缓存