Fill Forms, Validate E-Invoices, and Read PDF Metadata

This guide shows developers how to use PDFluent to handle interactive forms, process e-invoices, and manage document metadata. It is for Rust programmers working with PDFs.

PDF forms that actually fill.

Fill and flatten AcroForm PDF forms. Passes the PDF 1.7 conformance test suite (Adobe test corpus, 304 tests). Import data from FDF, XFDF, or JSON.

rust
use pdfluent::PdfDocument;

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("form.pdf")?;
    println!("{} form field(s)", doc.form_fields()?.len());

    doc.form_mut()
        .set_text("name", "Jane Smith")?
        .set_checkbox("subscribe", true)?;

    doc.save("filled.pdf")?;
    Ok(())
}

XFA forms work again. Without Adobe.

Migrate XFA-based PDF forms to modern standards with PDFluent. Flatten, convert, and extract data from XFA 3.3 forms without Adobe dependencies.

rust
// Planned 1.1 surface — see note above.
// 1.0-compatible variant: fill AcroForm fields + save.
use pdfluent::prelude::*;

fn main() -> Result<()> {
    let mut doc = PdfDocument::open("belastingaangifte_2024.pdf")?;

    {
        let mut form = doc.form_mut();
        form.set_text("bsn", "123456782")?
            .set_text("name", "Test User")?;
    }

    doc.save("belastingaangifte_2024_filled.pdf")?;
    Ok(())
}

Read and write PDF metadata.

Access XMP metadata, document information dictionary, and custom properties. Batch update metadata across thousands of files.

rust
use pdfluent::PdfDocument;

fn main() -> pdfluent::Result<()> {
    let mut doc = PdfDocument::open("input.pdf")?;

    // Read existing metadata
    let info = doc.metadata();
    println!("Title: {:?}", info.title);
    println!("Author: {:?}", info.author);

    // Write new metadata
    doc.metadata_mut()
        .set_title("Q1 2026 Financial Report")
        .set_author("Finance Team")
        .set_subject("Quarterly earnings")
        .set_keywords(&["earnings", "Q1", "2026"])
        .commit()?;

    doc.save("output.pdf")?;
    Ok(())
}