Opened from the filesystem. The iOS API reference will be blank — it fetches its content and needs a real origin. Run ./serve.sh in this directory.

PDFCora for Java

API referenceEvery public type, generated by Javadoc

Install

implementation("com.pdfcora:pdfcora-java:0.1.0")

The packages are not published yet. Until they are, build from source: see Getting a working checkout.

Java 17 or newer, macOS and Linux on x86-64 and arm64. The engine is a native library inside the jar, reached through JNI, not the Foreign Function API, so it runs on the JDK most teams already have rather than requiring 22+.

Open and render

try (PdfDocument document = PdfDocument.open(Path.of("contract.pdf"))) {
    BufferedImage image = document.page(0).render(1024);
    ImageIO.write(image, "png", new File("page-1.png"));
}

Every call on every document runs on one engine thread for the whole process, so calling from several threads is safe — the calls serialise rather than corrupting memory.

Open a Word file

try (PdfDocument document = PdfDocument.open(Path.of("letter.docx"))) {
    document.writeTo(Path.of("letter.pdf"));
}

open converts a DOCX to PDF; from then on it is an ordinary document. DOCX only — not .doc, XLSX or PPTX. The result depends on the fonts installed: see "Word documents" in the Java README.

Read a signature

for (PdfSignature signature : document.signatures()) {
    if (!signature.coversWholeDocument()) {
        // Valid, but content was appended after signing and is not protected.
    }
    PdfSignature.Verification result = signature.verify(bytes);
}

Integrity and trust are separate answers: verify says whether the signed bytes changed, not whether the certificate is trusted.

Redact it

PdfRedaction.Report report = document.redact(List.of(
    new PdfRedaction.Target.Region(0, rect),
    new PdfRedaction.Target.TextMatches("account number")));
byte[] clean = document.toByteArray();   // always a full save

Content is removed and the page's content stream regenerated, so the words leave the file — a black box drawn over text would leave every one of them in it.

Sign it

Pkcs12Signer signer = new Pkcs12Signer(Files.readAllBytes(identity), password);
byte[] signed = document.sign(PdfSignOptions.with(signer).reason("Approved"));

The CMS is built with JCA — no Bouncy Castle — and carries the CAdES signingCertificateV2 attribute, so the default ETSI.CAdES.detached sub-filter is honest about what it contains. document.sign signs a full save, so edits made in memory, such as the redaction above, are inside the signature; but that save rewrites the file, and a signature already in it does not survive. PdfSigning.sign(bytes, options) appends to bytes as they are, which is how a second signature leaves the first one verifying.

Tag an untagged document

PdfDocument tagged = document.tagContent(blocks, "Quarterly report", "en");

Objects in no block become artifacts, which is what makes the result conformant rather than merely tagged. veraPDF judges the output in the gates.

All platforms