How-to guides/Merge & Split

Merge PDFs in Rust

Combine multiple PDF files into one document. PDFluent preserves bookmarks across all input files.

rust
use pdfluent::prelude::*;

fn main() -> Result<()> {
    let merged = PdfMerger::new()
        .add(PdfDocument::open("part1.pdf")?)
        .add(PdfDocument::open("part2.pdf")?)
        .add(PdfDocument::open("part3.pdf")?)
        .build()?;

    merged.save("combined.pdf")?;

    println!("Merged {} pages into combined.pdf", merged.page_count());
    Ok(())
}
Install:cargo add pdfluent@1.0.0-beta.5Download SDK →

Step by step

1

Add PDFluent to your project

Add the pdfluent crate to your Cargo.toml. No system libraries are required.

rust
[dependencies]
pdfluent = "1"
2

Open each input document

Open every source PDF with PdfDocument::open. The merger takes full PdfDocument values by move, so consume each input once.

rust
use pdfluent::prelude::*;

let a = PdfDocument::open("invoice_jan.pdf")?;
let b = PdfDocument::open("invoice_feb.pdf")?;
let c = PdfDocument::open("invoice_mar.pdf")?;
3

Build a PdfMerger and add inputs

Create a PdfMerger, chain .add() for each document. Inputs are appended in the order they are added.

rust
let merger = PdfMerger::new()
    .add(a)
    .add(b)
    .add(c);
4

Configure bookmark handling

Choose a BookmarkMergeStrategy. Concat (the default) groups each source's bookmarks under a top-level entry; FlattenAll sequences them; Discard drops all bookmarks. In 1.0 Concat has dedicated treatment; FlattenAll and Discard fall back to the underlying concatenation.

rust
let merger = merger
    .with_bookmarks(BookmarkMergeStrategy::Concat)
    .with_page_labels(true); // 1.0: accepted but currently a no-op
5

Build and save

Call .build() to produce a merged PdfDocument, then save or serialise it. build() is the terminating step and consumes the merger.

rust
let merged = merger.build()?;
merged.save("annual_report.pdf")?;

println!("Total pages: {}", merged.page_count());

Notes and tips

  • Named destinations from each input file are remapped so they remain valid in the merged document.
  • Page labels from source files are treated on a best-effort basis in 1.0; full preservation lands in 1.1.
  • Encrypted PDFs must be decrypted before merging — open them with OpenOptions::new().with_password("...") or call doc.decrypt("...") first.
  • The merger processes inputs in the order they were added. Page numbering in the output starts at 1 and increases sequentially.
  • Input bytes: open from memory with PdfDocument::from_bytes(&bytes) before adding to the merger — there is no separate add_bytes entry point.

Why PDFluent for this

Pure Rust

No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.

Memory safe

Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.

Runs anywhere

Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.

Frequently asked questions