实现PDF文件添加水印的功能

发布于:2025-06-22 ⋅ 阅读:(19) ⋅ 点赞:(0)

通过Java代码实现PDF文件添加水印的功能,主要依赖iText库(用于PDF操作)和OSS SDK(可选,用于文件上传)。以下是实现的核心步骤:

首先添加依赖

<!-- 添加 PDF 水印 -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>

添加PDF水印的核心方法

@SpringBootTest
public class FileWatermarkUploader {
    // OSS 配置信息:需根据你的账号信息进行修改
    private static final String ENDPOINT = "your-endpoint";

    private static final String ACCESS_KEY_ID = "your-access-key";

    private static final String ACCESS_KEY_SECRET = "your-secret-key";

    private static final String BUCKET_NAME = "your-bucket-name";

    @Test
    public void T() throws Exception {
        uploadWithWatermark(new File("D:\\test.pdf"), "oss/path/output.pdf", "测试水印 - 保密 Confidential",
            "D:/output/output.pdf");

    }


    /**
     * 上传带水印的文件至 OSS,并保存到本地指定路径。
     *
     * @param inputFile 原始 PDF 文件
     * @param objectName OSS 上保存的文件名
     * @param watermarkText 自定义水印文字
     * @param outputPath 本地保存路径,如 "C:/output/watermarked.pdf"
     * @throws Exception 处理异常
     */
    public void uploadWithWatermark(File inputFile, String objectName, String watermarkText, String outputPath)
        throws Exception {
        // 判断是否是 PDF 文件
        if (!inputFile.getName().toLowerCase().endsWith(".pdf")) {
            throw new IllegalArgumentException("只支持 PDF 文件水印处理");
        }

        // 添加水印,返回本地水印文件
        File watermarkedFile = addPdfWatermark(inputFile, watermarkText);

        // 将临时文件复制到指定输出路径
        copyFile(watermarkedFile, new File(outputPath));

        // 上传到 OSS
        // uploadToOss(watermarkedFile, objectName);

        // 删除临时文件
        if (watermarkedFile.exists()) {
            watermarkedFile.delete();
        }
    }

    /**
     * 给 PDF 添加铺满整页的文字水印
     *
     * @param inputPdf 原始 PDF 文件
     * @param watermarkText 水印文字
     * @return 添加水印后的临时文件
     * @throws IOException IO 异常
     * @throws DocumentException PDF 处理异常
     */
    private File addPdfWatermark(File inputPdf, String watermarkText) throws IOException, DocumentException {
        File outputPdf = File.createTempFile("watermarked_", ".doc");

        PdfReader reader = new PdfReader(new FileInputStream(inputPdf));
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPdf));
        int totalPages = reader.getNumberOfPages();

        BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        PdfGState gs = new PdfGState();
        gs.setFillOpacity(0.5f);  // 半透明效果
        for (int i = 1; i <= totalPages; i++) {
            PdfContentByte canvas = stamper.getUnderContent(i);
            canvas.setGState(gs);
            canvas.setFontAndSize(font, 10);
            canvas.setColorFill(BaseColor.LIGHT_GRAY);

            float xSpacing = 150f; // 横向间隔
            float ySpacing = 100f; // 纵向间隔

            for (float x = 0; x < 595; x += xSpacing) { // 页面宽度 A4 约 595pt
                for (float y = 0; y < 842; y += ySpacing) { // 页面高度 A4 约 842pt
                    canvas.beginText();
                    canvas.showTextAligned(Element.ALIGN_CENTER, watermarkText, x, y, 45);
                    canvas.endText();
                }
            }
        }

        stamper.close();
        reader.close();
        return outputPdf;
    }

    /**
     * 上传文件至 OSS
     *
     * @param file 文件对象
     * @param objectName OSS 保存的文件名
     * @throws FileNotFoundException 文件找不到异常
     */
    private void uploadToOss(File file, String objectName) throws FileNotFoundException {
        OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        ossClient.putObject(BUCKET_NAME, objectName, new FileInputStream(file));
        ossClient.shutdown();
    }

    /**
     * 将文件从源路径复制到目标路径
     *
     * @param source 原始文件
     * @param destination 目标文件
     * @throws IOException IO 异常
     */
    private void copyFile(File source, File destination) throws IOException {
        try (InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(destination)) {
            byte[] buffer = new byte[1024];
            int length;
            while ((length = in.read(buffer)) > 0) {
                out.write(buffer, 0, length);
            }
        }
    }
}

关键点说明

  • iText依赖:需在项目中引入iText库(如com.itextpdf:itextpdf:5.2.0)。
  • 水印样式:通过PdfGState设置透明度,通过BaseFont设置字体,通过showTextAligned控制水印位置和旋转角度。
  • 水印密度:通过xSpacing和ySpacing调整水印排列密度。
  • 临时文件处理:生成水印文件后建议删除临时文件,避免存储浪费。

网站公告

今日签到

点亮在社区的每一天
去签到