SpringBoot implements pdf to add watermark

In some cases, we need to add watermark to PDF file to make it more recognizable or to protect its copyright. This article will introduce several solutions to add watermark to PDF.

Git address: https://gitee.com/ninesuntec/pdf-add-watermark

1. Use the Apache PDFBox library

PDFBox is a popular, free library written in Java that can be used to create, modify, and extract PDF content. PDFBox provides many APIs, including the ability to add text watermarks.

Add PDFBox dependency

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.24</version>
</dependency>

Before adding the watermark, the original PDF file needs to be read:

PDDocument document = PDDocument.load(new File("original.pdf"));

Iterate over all pages in a PDF and add watermarks using PDPageContentStream:

// 遍历 PDF 中的所有页面
for (int i = 0; i < document.getNumberOfPages(); i++) {
    
    
    PDPage page = document.getPage(i);
    PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);

    // 设置字体和字号
    contentStream.setFont(PDType1Font.HELVETICA_BOLD, 36);

    // 设置透明度
    contentStream.setNonStrokingColor(200, 200, 200);

    // 添加文本水印
    contentStream.beginText();
    contentStream.newLineAtOffset(100, 100); // 设置水印位置
    contentStream.showText("Watermark"); // 设置水印内容
    contentStream.endText();

    contentStream.close();
}

Finally, save the modified PDF file:

document.save(new File("output.pdf"));
document.close();

Example:

 public static void main(String[] args) throws IOException {
    
    
        // 读取原始 PDF 文件
        PDDocument document = PDDocument.load(new File("original.pdf"));

        // 遍历 PDF 中的所有页面
        for (int i = 0; i < document.getNumberOfPages(); i++) {
    
    
            PDPage page = document.getPage(i);
            PDPageContentStream contentStream = new PDPageContentStream(document, page, PDPageContentStream.AppendMode.APPEND, true, true);

            // 设置字体和字号
            contentStream.setFont(PDType1Font.HELVETICA_BOLD, 36);

            // 设置透明度
            contentStream.setNonStrokingColor(200, 200, 200);

            // 添加文本水印
            contentStream.beginText();
            contentStream.newLineAtOffset(100, 100); // 设置水印位置
            contentStream.showText("Watermark"); // 设置水印内容
            contentStream.endText();

            contentStream.close();
        }

        // 保存修改后的 PDF 文件
        document.save(new File("output.pdf"));
        document.close();
    }

In order to make our code more scalable, we extract some basic properties

PdfBoxAttributes:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PdfBoxAttributes {
    
    
    //透明度设置
    private Integer r = 200;
    private Integer g = 200;
    private Integer b = 200;
    //水印位置
    private float tx = 100;
    private float ty = 100;
    //水印内容
    private String showTxt = "PdfBoxWaterMark";
    //水印添加方式(覆盖、添加、)
    private PDPageContentStream.AppendMode appendMode = PDPageContentStream.AppendMode.APPEND;
    //字体样式
    private PDType1Font fontStyle = PDType1Font.HELVETICA_BOLD;
    private float fontSize = 36;
}

The usage is as follows:

import com.example.demo.po.PdfBoxAttributes;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import java.io.File;

public class PdfBoxWatermarkUtil {
    
    
    public static void addWaterMark(File pdf, String savePath, PdfBoxAttributes pdfBoxAttributes) {
    
    

        try {
    
    
            System.out.println("--------------开始添加水印--------------------");
            // 读取原始 PDF 文件
            PDDocument document = PDDocument.load(pdf);

            // 遍历 PDF 中的所有页面
            for (int i = 0; i < document.getNumberOfPages(); i++) {
    
    
                PDPage page = document.getPage(i);
                PDPageContentStream contentStream = new PDPageContentStream(document, page, pdfBoxAttributes.getAppendMode(), true, true);

                // 设置字体和字号
                contentStream.setFont(pdfBoxAttributes.getFontStyle(), pdfBoxAttributes.getFontSize());

                // 设置透明度
                contentStream.setNonStrokingColor(pdfBoxAttributes.getR(), pdfBoxAttributes.getG(), pdfBoxAttributes.getB());

                // 添加文本水印
                contentStream.beginText();
                contentStream.newLineAtOffset(pdfBoxAttributes.getTx(), pdfBoxAttributes.getTy()); // 设置水印位置
                contentStream.showText(pdfBoxAttributes.getShowTxt()); // 设置水印内容
                contentStream.endText();
                contentStream.close();
                System.out.println("--------------已完成第"+(i+1)+"页的水印添加--------------------");
            }

            // 保存修改后的 PDF 文件
            document.save(new File(savePath));
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }finally {
    
    
            System.out.println("--------------添加水印完成--------------------");
        }

    }

    public static void main(String[] args) {
    
    
        File file=new File("/Users/hb24795/Downloads/自动控制原理.pdf");
        addWaterMark(file,"/Users/hb24795/Downloads/自动控制原理1.pdf",new PdfBoxAttributes());
    }
}

insert image description here

2. Use the iText library

iText is a popular Java PDF library that can be used to create, read, modify and extract PDF content. iText provides many APIs, including the ability to add text watermarks.

add dependencies

       <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>

Before adding the watermark, the original PDF file needs to be read:

PdfReader reader = new PdfReader("original.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("output.pdf"));

Then, iterate over all pages in the PDF and add the watermark using PdfContentByte:

// 获取 PDF 中的页数
int pageCount = reader.getNumberOfPages();

// 添加水印
for (int i = 1; i <= pageCount; i++) {
    
    
    PdfContentByte contentByte = stamper.getUnderContent(i); // 或者 getOverContent()
    contentByte.beginText();
    contentByte.setFontAndSize(BaseFont.createFont(), 36f);
    contentByte.setColorFill(BaseColor.LIGHT_GRAY);
    contentByte.showTextAligned(Element.ALIGN_CENTER, "Watermark", 300, 400, 45);
    contentByte.endText();
}

Finally, the modified PDF file needs to be saved and the file stream closed:

stamper.close();
reader.close();

Example:

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;

import java.io.FileOutputStream;
import java.io.IOException;

public class ItextWatermark {
    
    
    public static void main(String[] args) throws IOException, DocumentException {
    
    
        // 读取原始 PDF 文件
        PdfReader reader = new PdfReader("original.pdf");
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("output.pdf"));

        // 获取 PDF 中的页数
        int pageCount = reader.getNumberOfPages();

        // 添加水印
        for (int i = 1; i <= pageCount; i++) {
    
    
            PdfContentByte contentByte = stamper.getUnderContent(i); // 或者 getOverContent()
            contentByte.beginText();
            contentByte.setFontAndSize(BaseFont.createFont(), 36f);
            contentByte.setColorFill(BaseColor.LIGHT_GRAY);
            contentByte.showTextAligned(Element.ALIGN_CENTER, "Watermark", 300, 400, 45);
            contentByte.endText();
        }

        // 保存修改后的 PDF 文件并关闭文件流
        stamper.close();
        reader.close();
    }
}

Similarly, we extract him into a tool class

import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.pdf.BaseFont;
import lombok.Data;

import java.io.IOException;

@Data
public class ITextAttributes {
    
    
    //字体样式
    private BaseFont fontStyle = BaseFont.createFont();
    //字体大小
    private float fontSize = 36f;
    //字体颜色
    private BaseColor fontColor = BaseColor.LIGHT_GRAY;
    //水印位置
    private int location = Element.ALIGN_CENTER;
    //水印内容
    private String showTxt = "ITextWaterMark";
    //坐标以及旋转角度
    private float x = 300, y = 400, rotation = 45;


    public ITextAttributes() throws DocumentException, IOException {
    
    
    }

    public ITextAttributes(BaseFont fontStyle, float fontSize, BaseColor fontColor, int location, String showTxt, float x, float y, float rotation)throws DocumentException, IOException  {
    
    
        this.fontStyle = fontStyle;
        this.fontSize = fontSize;
        this.fontColor = fontColor;
        this.location = location;
        this.showTxt = showTxt;
        this.x = x;
        this.y = y;
        this.rotation = rotation;
    }
}

import com.example.demo.po.ITextAttributes;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class ItextWatermarkUtil {
    
    
    public static void addWaterMark(String pdfPath, String outPath, ITextAttributes attributes) {
    
    
        try {
    
    
            System.out.println("--------------开始添加水印--------------------");
            // 读取原始 PDF 文件
            PdfReader reader = new PdfReader(pdfPath);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outPath));
            // 获取 PDF 中的页数
            int pageCount = reader.getNumberOfPages();

            // 添加水印
            for (int i = 1; i <= pageCount; i++) {
    
    
                PdfContentByte contentByte = stamper.getUnderContent(i); // 或者 getOverContent()
                contentByte.beginText();
                contentByte.setFontAndSize(attributes.getFontStyle(), attributes.getFontSize());
                contentByte.setColorFill(attributes.getFontColor());
                contentByte.showTextAligned(attributes.getLocation(), attributes.getShowTxt(), attributes.getX(), attributes.getY(), attributes.getRotation());
                contentByte.endText();
                System.out.println("--------------已完成第" + (i) + "页的水印添加--------------------");
            }

            // 保存修改后的 PDF 文件并关闭文件流
            stamper.close();
            reader.close();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            System.out.println("--------------添加水印完成--------------------");
        }

    }

    public static void main(String[] args) throws DocumentException, IOException {
    
    
        addWaterMark("/Users/hb24795/Downloads/自动控制原理.pdf", "/Users/hb24795/Downloads/自动控制原理1.pdf", new ITextAttributes());
    }
}

insert image description here

3.Free Spire.PDF for Java

Free Spire.PDF for Java is a free Java PDF library that provides an easy-to-use API for creating, reading, modifying and extracting PDF content. Free Spire.PDF for Java also supports adding text watermarks and image watermarks.

Official document address: https://www.e-iceblue.cn/licensing/install-spirepdf-for-java-from-maven-repository.html

add dependencies

Configure the warehouse path in maven's settiing.xml
insert image description here

	<profile>
     <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <url>http://repo.e-iceblue.cn/repository/maven-public/</url>
        </repository>
    </repositories>
    </profile>

Then add dependencies to the pom file

        <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.pdf.free</artifactId>
            <version>3.11.6</version>
        </dependency>

If you really don’t know how to configure it, you can download the jar package. The download address is as follows: https://repo.e-iceblue.cn/repository/maven-public/e-iceblue/spire.pdf.free/5.1.0/ spire.pdf.free-5.1.0.jar
and then reference the jar package in the project. For specific operations, please refer to: "springBoot references external jar packages"

Before adding the watermark, the original PDF file needs to be read:

PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("original.pdf");

Then, iterate over all pages in the PDF and add the watermark using PdfPageBase:

// 遍历 PDF 中的所有页面
for (int i = 0; i < pdf.getPages().getCount(); i++) {
    
    
    PdfPageBase page = pdf.getPages().get(i);

    //添加文本水印
   AddTextWatermark(page, bandge);
}

Finally, the modified PDF file needs to be saved:

pdf.saveToFile("output.pdf");
pdf.close();

Example:

import com.spire.pdf.*;
import com.spire.pdf.annotations.PdfWatermarkAnnotationWidget;
import com.spire.pdf.graphics.*;

import java.awt.*;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

public class FreeSpirePdfWatermarkUtil {
    
    
    enum METHOD {
    
    
        image,
        text
    }

    /**
     * 使用FreeSpire添加水印
     *
     * @param pdfPath    pdf文件路径
     * @param bandge
     * @param outputPath
     */
    public static void addWaterMark(String pdfPath, String bandge, METHOD method, String outputPath) {
    
    
        try {
    
    
            String addMethod = method == METHOD.text ? "文本" : "图片";
            System.out.println("--------------开始添加" + addMethod + "水印--------------------");
            // 读取原始 PDF 文件
            PdfDocument pdf = new PdfDocument();
            pdf.loadFromFile(pdfPath);

            // 遍历 PDF 中的所有页面
            for (int i = 0; i < pdf.getPages().getCount(); i++) {
    
    
                PdfPageBase page = pdf.getPages().get(i);
                switch (method) {
    
    
                    case text:
                        //添加文本水印
                        AddTextWatermark(page, bandge);
                        break;
                    case image:
                        // 添加图片水印
                        AddImageWatermark(page, bandge);
                }
                System.out.println("--------------已完成第" + (i+1) + "页的水印添加--------------------");
            }
            // 保存修改后的 PDF 文件
            pdf.saveToFile(outputPath);
            pdf.close();
            System.out.println("--------------已完成文件的水印添加--------------------");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }


    /**
     * @param page      要添加水印的页面
     * @param imageFile 水印图片路径
     */
    public static void AddImageWatermark(PdfPageBase page, String imageFile) {
    
    
        page.setBackgroundImage(imageFile);
        Rectangle2D rect = new Rectangle2D.Float();
        rect.setFrame(page.getClientSize().getWidth() / 2 - 100, page.getClientSize().getHeight() / 2 - 100, 200, 200);
        page.setBackgroundRegion(rect);
    }

    static void AddTextWatermark(PdfPageBase page, String textWatermark) {
    
    
        Dimension2D dimension2D = new Dimension();
        dimension2D.setSize(page.getCanvas().getClientSize().getWidth() / 2, page.getCanvas().getClientSize().getHeight() / 3);
        PdfTilingBrush brush = new PdfTilingBrush(dimension2D);
        brush.getGraphics().setTransparency(0.3F);
        brush.getGraphics().save();
        brush.getGraphics().translateTransform((float) brush.getSize().getWidth() / 2, (float) brush.getSize().getHeight() / 2);
        brush.getGraphics().rotateTransform(-45);
        brush.getGraphics().drawString(textWatermark, new PdfTrueTypeFont(new Font("Arial Unicode MS", Font.PLAIN, 30), true), PdfBrushes.getRed(), 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
        brush.getGraphics().restore();
        brush.getGraphics().setTransparency(1);
        Rectangle2D loRect = new Rectangle2D.Float();
        loRect.setFrame(new Point2D.Float(0, 0), page.getCanvas().getClientSize());
        page.getCanvas().drawRectangle(brush, loRect);
    }


    public static void main(String[] args) {
    
    
//        addWaterMark("/Users/hb24795/Downloads/自动控制原理.pdf", "FreeSpire", METHOD.text, "/Users/hb24795/Downloads/自动控制原理1.pdf");
        addWaterMark("/Users/hb24795/Downloads/自动控制原理.pdf", "/Users/hb24795/Downloads/水印模板.png", METHOD.image, "/Users/hb24795/Downloads/自动控制原理1.pdf");
    }

}

insert image description here

insert image description here

Of course, its functions are far more than that. You can study it through the official documents. Because this article mainly studies the operation of watermarks, it will not be used here to refine the tools.

4.Aspose.PDF for Java

Aspose.PDF for Java is a powerful PDF processing library that provides the function of adding watermarks.

Add maven dependency

        <dependency>
            <groupId>com.luhuiguo</groupId>
            <artifactId>aspose-pdf</artifactId>
            <version>22.4</version>
        </dependency>

Add text watermark

@PostMapping("/addTextWatermark")
public ResponseEntity<byte[]> addTextWatermark(@RequestParam("file") MultipartFile file) throws IOException {
    
    
    // 加载 PDF 文件
    Document pdfDocument = new Document(file.getInputStream());
    TextStamp textStamp = new TextStamp("Watermark");
    textStamp.setWordWrap(true);
    textStamp.setVerticalAlignment(VerticalAlignment.Center);
    textStamp.setHorizontalAlignment(HorizontalAlignment.Center);
    pdfDocument.getPages().get_Item(1).addStamp(textStamp);

    // 保存 PDF 文件
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    pdfDocument.save(outputStream);
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"watermarked.pdf\"")
            .contentType(MediaType.APPLICATION_PDF)
            .body(outputStream.toByteArray());
}

Add image watermark

@PostMapping("/addImageWatermark")
public ResponseEntity<byte[]> addImageWatermark(@RequestParam("file") MultipartFile file) throws IOException {
    
    
    // 加载 PDF 文件
    Document pdfDocument = new Document(file.getInputStream());
    ImageStamp imageStamp = new ImageStamp("watermark.png");
    imageStamp.setWidth(100);
    imageStamp.setHeight(100);
    imageStamp.setVerticalAlignment(VerticalAlignment.Center);
    imageStamp.setHorizontalAlignment(HorizontalAlignment.Center);
    pdfDocument.getPages().get_Item(1).addStamp(imageStamp);

    // 保存 PDF 文件
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    pdfDocument.save(outputStream);
    return ResponseEntity.ok()
            .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"watermarked.pdf\"")
            .contentType(MediaType.APPLICATION_PDF)
            .body(outputStream.toByteArray());
}

Extract it as a tool class

import com.aspose.pdf.*;

import java.io.*;

public class AsposeWatermarkUtil {
    
    
    enum METHOD {
    
    
        IMAGE,
        TEXT
    }

    public static void addWaterMark(String filePath, METHOD method, String bandge, String outPath) {
    
    
        String addMethod = method == METHOD.TEXT ? "文本" : "图片";
        System.out.println("--------------开始添加" + addMethod + "水印--------------------");
        try {
    
    
            File pdf = new File(filePath);
            // 加载 PDF 文件
            Document pdfDocument = new Document(new FileInputStream(pdf));
            for (int i = 1; i <= pdfDocument.getPages().size(); i++) {
    
    
                Page page = pdfDocument.getPages().get_Item(i);
                if (method == METHOD.IMAGE) {
    
    
                    addImageWatermark(bandge, page);
                } else {
    
    
                    addTextWatermark(bandge, page);
                }
                System.out.println("--------------已完成第" + (i) + "页的水印添加--------------------");
            }
            // 保存 PDF 文件
            OutputStream outputStream = new FileOutputStream(outPath);
            pdfDocument.save(outputStream);
            System.out.println("--------------已完成文件的水印添加--------------------");
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
    }

    public static void addImageWatermark(String imagePath, Page page) {
    
    
        ImageStamp imageStamp = new ImageStamp(imagePath);
        imageStamp.setWidth(100);
        imageStamp.setHeight(100);
        imageStamp.setVerticalAlignment(VerticalAlignment.Center);
        imageStamp.setHorizontalAlignment(HorizontalAlignment.Center);
        imageStamp.setOpacity(0.2);
        page.addStamp(imageStamp);
    }

    public static void addTextWatermark(String text, Page page) {
    
    
        TextStamp textStamp = new TextStamp(text);
        textStamp.setWordWrap(true);
        textStamp.setVerticalAlignment(VerticalAlignment.Center);
        textStamp.setHorizontalAlignment(HorizontalAlignment.Center);
        textStamp.setOpacity(0.5);
        textStamp.setRotate(25);

        page.addStamp(textStamp);
    }

    public static void main(String[] args) {
    
    
//        addWaterMark("/Users/hb24795/Downloads/自动控制原理.pdf", METHOD.TEXT,"Aspose", "/Users/hb24795/Downloads/自动控制原理1.pdf");
        addWaterMark("/Users/hb24795/Downloads/自动控制原理.pdf", METHOD.IMAGE, "/Users/hb24795/Downloads/水印模板.png", "/Users/hb24795/Downloads/自动控制原理1.pdf");
    }
}

Each of the four tools mentioned above can operate other types of files, such as word, ppt, etc., and can remove watermarks, etc. You can check relevant information and try it yourself

More operations on Pdf by the above tools will be given later, such as converting pdf to image, merging Pdf, removing watermark, etc.

Guess you like

Origin blog.csdn.net/zhiyikeji/article/details/131628968
Recommended