XFA forms do not open correctly in many PDF readers. Converting to AcroForm makes your PDFs compatible with Preview, browsers, and any standard PDF viewer.
use pdfluent::{PdfDocument, XfaToAcroformOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = PdfDocument::open("xfa-form.pdf")?;
let opts = XfaToAcroformOptions::default()
.preserve_values(true)
.flatten_static_content(false);
doc.convert_xfa_to_acroform(opts)?;
doc.save("acroform-output.pdf")?;
Ok(())
}XFA-to-AcroForm conversion requires both the xfa and acroform feature flags.
# Cargo.toml
[dependencies]
pdfluent = { version = "0.9", features = ["xfa", "acroform"] }Open the source PDF. Call has_xfa() to confirm it contains an XFA form before converting.
use pdfluent::PdfDocument;
let mut doc = PdfDocument::open("xfa-form.pdf")?;
if !doc.has_xfa() {
eprintln!("No XFA form found. Skipping conversion.");
return Ok(());
}preserve_values carries over any data already entered into the XFA form. flatten_static_content burns non-interactive XFA graphics into the page as static content.
use pdfluent::XfaToAcroformOptions;
let opts = XfaToAcroformOptions::default()
.preserve_values(true)
.flatten_static_content(false)
.page_size_from_xfa(true);convert_xfa_to_acroform() rewrites the document in place. The XFA streams are removed and replaced with AcroForm fields at the correct positions.
doc.convert_xfa_to_acroform(opts)?;
let field_count = doc.acroform()?.fields().count();
println!("Converted {} fields to AcroForm", field_count);The output file is a standard PDF with no XFA dependency. It opens in any PDF viewer.
doc.save("acroform-output.pdf")?;
println!("Saved acroform-output.pdf");No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.