How to Add Watermarks to PDFs with Spring Boot: PDFBox, iText, Ghostscript, and More
This article walks through multiple ways to add text or image watermarks to PDF files in a Spring Boot application, covering Apache PDFBox, iText, Ghostscript command‑line, Free Spire.PDF, and Aspose.PDF, with Maven dependencies, step‑by‑step code examples, and practical tips for preserving original documents.
PDF watermarking in Spring Boot
1. Apache PDFBox
Add the PDFBox library to pom.xml:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.24</version>
</dependency>Load the source PDF, iterate over each page and use PDPageContentStream to draw the watermark text.
PDDocument document = PDDocument.load(new File("original.pdf"));
for (int i = 0; i < document.getNumberOfPages(); i++) {
PDPage page = document.getPage(i);
PDPageContentStream cs = new PDPageContentStream(document, page,
PDPageContentStream.AppendMode.APPEND, true, true);
cs.setFont(PDType1Font.HELVETICA_BOLD, 36);
cs.setNonStrokingColor(200, 200, 200);
cs.beginText();
cs.newLineAtOffset(100, 100);
cs.showText("Watermark");
cs.endText();
cs.close();
}
document.save(new File("output.pdf"));
document.close();2. iText 5.x
Add the iText dependency:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>Read the PDF, obtain a PdfStamper, and write the watermark on each page:
PdfReader reader = new PdfReader("original.pdf");
PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("output.pdf"));
int pageCount = reader.getNumberOfPages();
for (int i = 1; i <= pageCount; i++) {
PdfContentByte cb = stamper.getUnderContent(i);
cb.beginText();
cb.setFontAndSize(BaseFont.createFont(), 36f);
cb.setColorFill(BaseColor.LIGHT_GRAY);
cb.showTextAligned(Element.ALIGN_CENTER, "Watermark", 300, 400, 45);
cb.endText();
}
stamper.close();
reader.close();3. Ghostscript (command‑line)
Install Ghostscript for your OS (Windows/macOS/Linux) and run:
gs -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=output.pdf \
-c "newpath /Helvetica-Bold findfont 36 scalefont setfont 0.5 setgray 200 200 moveto (Watermark) show showpage" original.pdfKey options: -sDEVICE=pdfwrite – output format PDF. -sOutputFile=output.pdf – name of the resulting file.
The last argument ( original.pdf) is the source file.
The string inside quotes defines the watermark text, font, size, colour and position.
Back up the source PDF before running the command because Ghostscript writes directly to the output file.
4. Free Spire.PDF for Java
Add the free Spire.PDF dependency:
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>free-spire-pdf-for-java</artifactId>
<version>1.9.6</version>
</dependency>Load the PDF, iterate pages and add a text watermark:
PdfDocument pdf = new PdfDocument();
pdf.loadFromFile("original.pdf");
for (int i = 0; i < pdf.getPages().getCount(); i++) {
PdfPageBase page = pdf.getPages().get(i);
PdfWatermark wm = new PdfWatermark("Watermark");
wm.setFont(new PdfFont(PdfFontFamily.Helvetica, 36));
wm.setOpacity(0.5f);
page.getWatermarks().add(wm);
}
pdf.saveToFile("output.pdf");
pdf.close();5. Aspose.PDF for Java
Add the Aspose.PDF dependency:
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-pdf</artifactId>
<version>21.4</version>
</dependency>Spring Boot controller that adds a text watermark:
@PostMapping("/addTextWatermark")
public ResponseEntity<byte[]> addTextWatermark(@RequestParam("file") MultipartFile file) throws IOException {
Document pdf = new Document(file.getInputStream());
TextStamp stamp = new TextStamp("Watermark");
stamp.setWordWrap(true);
stamp.setVerticalAlignment(VerticalAlignment.Center);
stamp.setHorizontalAlignment(HorizontalAlignment.Center);
pdf.getPages().get_Item(1).addStamp(stamp);
ByteArrayOutputStream out = new ByteArrayOutputStream();
pdf.save(out);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"watermarked.pdf\"")
.contentType(MediaType.APPLICATION_PDF)
.body(out.toByteArray());
}Controller that adds an image watermark:
@PostMapping("/addImageWatermark")
public ResponseEntity<byte[]> addImageWatermark(@RequestParam("file") MultipartFile file) throws IOException {
Document pdf = new Document(file.getInputStream());
ImageStamp imgStamp = new ImageStamp("watermark.png");
imgStamp.setWidth(100);
imgStamp.setHeight(100);
imgStamp.setVerticalAlignment(VerticalAlignment.Center);
imgStamp.setHorizontalAlignment(HorizontalAlignment.Center);
pdf.getPages().get_Item(1).addStamp(imgStamp);
ByteArrayOutputStream out = new ByteArrayOutputStream();
pdf.save(out);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"watermarked.pdf\"")
.contentType(MediaType.APPLICATION_PDF)
.body(out.toByteArray());
}Full controller class (text and image endpoints) combines the two methods above.
References
Ghostscript download: https://www.ghostscript.com/download/gsdnld.html
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
