Apache PDFBox
| Language | Java 8+ |
|---|---|
| License | Apache-2.0 |
| Repository | github.com/apache/pdfbox |
| Documentation | pdfbox.apache.org, migration guide to 3.0 |
| Depends on | commons-logging; optional Bouncy Castle (signatures, certificate encryption), JAI codecs for JPEG 2000 and JBIG2 |
| Read / write | yes / yes: text extraction, rendering, merge, split, forms, annotations, encryption, signatures, page creation |
PDFBox is the Apache Software Foundation’s PDF library. It parses PDFs (also many broken ones), extracts text with PDFTextStripper, renders pages to BufferedImage with Java2D, merges and splits documents, fills and flattens AcroForms, encrypts and decrypts, and signs documents. Apache Tika uses it for PDF text extraction. A pdfbox-app jar provides command-line tools (export:text, render, merge, split, encrypt, decrypt).
Creating new documents works at the content-stream level: you set fonts and positions yourself, with no line wrapping or tables. Version 3.0 changed the API: files are loaded with Loader.loadPDF, and standard fonts are created with new PDType1Font(Standard14Fonts.FontName.HELVETICA).
Installation#
Maven:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.8</version>
</dependency>
Gradle:
implementation("org.apache.pdfbox:pdfbox:3.0.8")
Basic usage: extract text from a PDF#
import java.io.File;
import java.io.IOException;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
public class ExtractText {
public static void main(String[] args) throws IOException {
try (PDDocument doc = Loader.loadPDF(new File("in.pdf"))) {
System.out.println(doc.getNumberOfPages() + " pages");
PDFTextStripper stripper = new PDFTextStripper();
stripper.setSortByPosition(true); // reading order by position, helps with columns
stripper.setStartPage(1);
stripper.setEndPage(doc.getNumberOfPages());
System.out.println(stripper.getText(doc));
}
}
}
How to render a PDF page to an image#
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
try (PDDocument doc = Loader.loadPDF(new File("in.pdf"))) {
PDFRenderer renderer = new PDFRenderer(doc);
for (int i = 0; i < doc.getNumberOfPages(); i++) {
BufferedImage image = renderer.renderImageWithDPI(i, 150, ImageType.RGB);
ImageIO.write(image, "png", new File("page-" + (i + 1) + ".png"));
}
}
How to merge PDF files#
import java.io.File;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
PDFMergerUtility merger = new PDFMergerUtility();
merger.addSource(new File("a.pdf"));
merger.addSource(new File("b.pdf"));
merger.setDestinationFileName("merged.pdf");
merger.mergeDocuments(IOUtils.createMemoryOnlyStreamCache());
How to split a PDF into pages#
import java.util.List;
import org.apache.pdfbox.multipdf.Splitter;
try (PDDocument doc = Loader.loadPDF(new File("in.pdf"))) {
Splitter splitter = new Splitter();
splitter.setSplitAtPage(1); // one page per document
List<PDDocument> parts = splitter.split(doc);
for (int i = 0; i < parts.size(); i++) {
try (PDDocument part = parts.get(i)) {
part.save("page-" + (i + 1) + ".pdf");
}
}
}
How to create a PDF with text#
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage(PDRectangle.A4);
doc.addPage(page);
PDType1Font font = new PDType1Font(Standard14Fonts.FontName.HELVETICA_BOLD);
try (PDPageContentStream cs = new PDPageContentStream(doc, page)) {
cs.beginText();
cs.setFont(font, 24);
cs.newLineAtOffset(72, 770); // origin is bottom-left
cs.showText("Hello, PDF!");
cs.endText();
}
doc.getDocumentInformation().setTitle("Hello");
doc.save("hello.pdf");
}
Standard 14 fonts only cover WinAnsi characters; for other text load a TrueType font with PDType0Font.load(doc, new File("DejaVuSans.ttf")).
How to fill a PDF form#
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.pdmodel.interactive.form.PDField;
try (PDDocument doc = Loader.loadPDF(new File("form.pdf"))) {
PDAcroForm form = doc.getDocumentCatalog().getAcroForm();
for (PDField field : form.getFieldTree())
System.out.println(field.getFullyQualifiedName() + " = " + field.getValueAsString());
form.getField("name").setValue("Jane Doe");
form.flatten(); // optional
doc.save("filled.pdf");
}
How to rotate pages, read metadata and encrypt#
import org.apache.pdfbox.pdmodel.PDDocumentInformation;
import org.apache.pdfbox.pdmodel.encryption.AccessPermission;
import org.apache.pdfbox.pdmodel.encryption.StandardProtectionPolicy;
try (PDDocument doc = Loader.loadPDF(new File("in.pdf"))) {
PDDocumentInformation info = doc.getDocumentInformation();
System.out.println("Title: " + info.getTitle() + ", Author: " + info.getAuthor()
+ ", PDF " + doc.getVersion());
for (PDPage page : doc.getPages())
page.setRotation((page.getRotation() + 90) % 360);
AccessPermission ap = new AccessPermission();
ap.setCanModify(false);
StandardProtectionPolicy policy = new StandardProtectionPolicy("owner", "user", ap);
policy.setEncryptionKeyLength(256); // AES-256
doc.protect(policy);
doc.save("out.pdf");
}
// decrypt: open with the password and remove security
try (PDDocument doc = Loader.loadPDF(new File("out.pdf"), "owner")) {
doc.setAllSecurityToBeRemoved(true);
doc.save("decrypted.pdf");
}
Tips#
Loader.loadPDF(file, password, null, null, IOUtils.createTempFileOnlyStreamCache())keeps memory use low for huge files.- For text with positions, subclass
PDFTextStripperand overridewriteString(String, List<TextPosition>). - Add
jai-imageio-jpeg2000andjbig2-imageioto the classpath to render pages with JPEG 2000 and JBIG2 images.