Editing PDF documents programmatically involves a wide range of tasks: inserting new pages, adding text and images, replacing existing content, removing unwanted elements, and applying security measures like watermarks and encryption. In this post, I’ll share practical Java code snippets for each of these common editing scenarios, based on my recent project experience.
1. Environment Setup
Before diving into code, you need to include a PDF library in your project. I chose Spire.PDF for Java because of its rich API and ease of use. If you are using Maven, add the following repository and dependency to your pom.xml:
<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.com/nexus/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.pdf</artifactId>
<version>11.9.6</version>
</dependency>
</dependencies>
If you are not using Maven, download the JAR package from the official website and add it to your project’s classpath.
2. Loading a Document
All operations start with loading an existing PDF file into a PdfDocument object:
PdfDocument doc = new PdfDocument();
doc.loadFromFile("C:\\work\\sample.pdf");
The loadFromFile method accepts a file path (absolute or relative). Once loaded, the document is ready for manipulation.
3. Adding Content
3.1 Adding a Page
To append a new page at the end of the document, use getPages().add():
PdfPageBase newPage = doc.getPages().add(PdfPageSize.A4, new PdfMargins(54));
newPage.getCanvas().drawString("This is the newly added page.",
new PdfTrueTypeFont(new Font("Arial", Font.PLAIN, 18)),
PdfBrushes.getBlue(), 0, 0);
This creates an A4 page with 54‑point margins on both sides and draws blue text at the top‑left corner.
3.2 Adding Text on an Existing Page
If you need to place text within a specific rectangular area (with automatic line wrapping), define a Rectangle2D.Float:
PdfPageBase page = doc.getPages().get(0);
Rectangle2D.Float rect = new Rectangle2D.Float(54, 300, 400, 100);
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Times New Roman", Font.PLAIN, 14));
PdfSolidBrush brush = new PdfSolidBrush(new PdfRGBColor(Color.BLACK));
page.getCanvas().drawString("This text will be drawn inside the defined rectangle and wraps automatically.", font, brush, rect);
The text will fit within the rectangle, making it ideal for filling form fields or adding annotations.
3.3 Inserting an Image
Inserting an image (e.g., logo or signature) is straightforward:
PdfImage image = PdfImage.fromFile("C:\\work\\logo.png");
page.getCanvas().drawImage(image, 100, 500);
fromFile loads the image, and drawImage places it at the specified (x, y) coordinates. You can also scale the image by using an overload that accepts width and height.
3.4 Adding a Table
Tables are essential for data presentation. Spire.PDF can generate a table directly from a two‑dimensional array:
PdfTable table = new PdfTable();
String[][] data = {
{"Name", "Department", "Year"},
{"Alice", "R&D", "2019"},
{"Bob", "Marketing", "2020"},
{"Charlie", "Finance", "2018"}
};
table.setDataSource(data);
// Customise table style
PdfTableStyle style = new PdfTableStyle();
style.getDefaultStyle().setFont(new PdfTrueTypeFont(new Font("Arial", Font.PLAIN, 12)));
table.setStyle(style);
// Draw the table on the page
table.draw(page, new Point2D.Float(50, 200));
setDataSource accepts the data, and draw places the table at the given top‑left position. You can further customise borders, background, and font.
3.5 Adding an Annotation
Popup annotations improve interactivity—for example, adding a comment or reminder:
PdfPopupAnnotation popup = new PdfPopupAnnotation();
popup.setLocation(new Point2D.Double(200, 400));
popup.setText("Please verify these figures.");
popup.setIcon(PdfPopupIcon.Comment);
popup.setColor(new PdfRGBColor(Color.YELLOW));
page.getAnnotations().add(popup);
setLocation sets the annotation icon position, setText defines the tooltip content, and the annotation is added to the page’s collection.
4. Replacing Content
4.1 Replacing Text
To replace all occurrences of a specific word (case‑insensitive, for instance):
PdfTextReplaceOptions options = new PdfTextReplaceOptions();
options.setReplaceType(EnumSet.of(ReplaceActionType.IgnoreCase));
for (int i = 0; i < doc.getPages().getCount(); i++) {
PdfPageBase page = doc.getPages().get(i);
PdfTextReplacer replacer = new PdfTextReplacer(page);
replacer.setOptions(options);
replacer.replaceAllText("Water", "H₂O");
}
PdfTextReplacer processes each page. Note that this only works for real text content, not images or scanned pages.
4.2 Replacing an Image
When you need to update an image (e.g., a logo) in the PDF:
PdfImageHelper helper = new PdfImageHelper();
PdfImageInfo[] imageInfos = helper.getImagesInfo(page); // get all images on the page
PdfImage newImage = PdfImage.fromFile("C:\\work\\new_logo.png");
helper.replaceImage(imageInfos[0], newImage); // replace the first image
getImagesInfo returns an array of image metadata; replaceImage swaps the old image with the new one. You can loop through the array to replace a specific image based on position or other criteria.
5. Removing Content
5.1 Removing a Page
doc.getPages().removeAt(0); // deletes the first page
removeAt takes the zero‑based index of the page to remove.
5.2 Removing an Image
helper.deleteImage(imageInfos[0]);
Using the same PdfImageHelper, you can delete a specific image.
5.3 Removing an Annotation
page.getAnnotationsWidget().removeAt(0);
getAnnotationsWidget returns the annotation collection; removeAt deletes the annotation at the given index.
5.4 Removing an Attachment
If the document contains embedded attachments (e.g., another PDF or Excel file):
PdfAttachmentCollection attachments = doc.getAttachments();
if (attachments.size() > 0) {
attachments.removeAt(0);
}
Always check the size before removing to avoid index errors.
6. Security Protection
6.1 Adding a Watermark
Watermarks are often used for branding or confidentiality. The code below draws a semi‑transparent “CONFIDENTIAL” text centered on every page:
PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("Arial Black", Font.PLAIN, 50), true);
String watermark = "CONFIDENTIAL";
float opacity = 0.3f;
for (int i = 0; i < doc.getPages().getCount(); i++) {
PdfPageBase page = doc.getPages().get(i);
page.getCanvas().setTransparency(opacity);
Dimension2D textSize = font.measureString(watermark);
double x = (page.getActualSize().getWidth() - textSize.getWidth()) / 2;
double y = (page.getActualSize().getHeight() - textSize.getHeight()) / 2;
page.getCanvas().drawString(watermark, font, PdfBrushes.getGray(), x, y);
}
setTransparency controls the opacity, and measureString helps centre the text both horizontally and vertically.
6.2 Encrypting with a Password
To protect sensitive documents, use AES‑256 encryption and set permissions:
String userPassword = "user123";
String ownerPassword = "admin456";
PdfPasswordSecurityPolicy policy = new PdfPasswordSecurityPolicy(userPassword, ownerPassword);
policy.setEncryptionAlgorithm(PdfEncryptionAlgorithm.AES_256);
policy.setDocumentPrivilege(PdfDocumentPrivilege.getAllowAll());
policy.getDocumentPrivilege().setAllowModifyContents(false);
policy.getDocumentPrivilege().setAllowContentCopying(false);
doc.encrypt(policy);
userPassword is required to open the document, while ownerPassword controls permissions (e.g., printing, editing, copying). The setDocumentPrivilege method lets you fine‑tune what users are allowed to do.
7. Saving and Releasing Resources
After all modifications, save the document to a new file and close it:
doc.saveToFile("C:\\work\\output.pdf");
doc.close();
It is recommended to save under a different name to preserve the original file.
Final Thoughts
These code snippets cover the core PDF editing tasks I frequently encounter—inserting content, replacing text and images, removing elements, and applying security measures. One thing to keep in mind: text replacement works reliably only for selectable text, not scanned images, so always verify the source PDF type before processing. Also, remember to handle file paths carefully to avoid encoding issues. With these basics, you should be able to build more complex PDF workflows without reinventing the wheel.
Comments
Post a Comment