How-to guides/Merge & Split

Split a PDF by page range in Rust

Extract one or more page ranges from a PDF and write each range to a separate file. Useful for splitting chapters, invoices, or reports.

rust
use pdfluent::{PdfDocument, PageRange};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let doc = PdfDocument::open("report.pdf")?;

    doc.split_by_ranges(&[
        PageRange::new(1, 10),
        PageRange::new(11, 20),
        PageRange::new(21, doc.page_count()),
    ])
    .write_files("chapter_{n}.pdf")?;

    Ok(())
}
Install:cargo add pdfluentDownload SDK →

Step by step

1

Open the source document

Load the PDF you want to split. PDFluent reads the file lazily, so opening a 500-page document uses minimal memory until pages are accessed.

rust
use pdfluent::PdfDocument;

let doc = PdfDocument::open("quarterly_report.pdf")?;
println!("Source has {} pages", doc.page_count());
2

Define page ranges

Create PageRange values for each segment. Pages are 1-indexed. Ranges can overlap if you need the same page in multiple output files.

rust
use pdfluent::PageRange;

let ranges = vec![
    PageRange::new(1, 5),    // cover + intro
    PageRange::new(6, 18),   // body
    PageRange::new(19, 22),  // appendix
];
3

Split and write to separate files

Pass the ranges to split_by_ranges(). Use {n} in the output pattern for the range index, or provide a Vec of explicit output paths.

rust
doc.split_by_ranges(&ranges)
    .write_files("segment_{n}.pdf")?;
// Produces: segment_1.pdf, segment_2.pdf, segment_3.pdf
4

Use explicit output names

When you need specific filenames, pass a slice of paths with the same length as the ranges slice.

rust
let output_paths = ["cover.pdf", "body.pdf", "appendix.pdf"];

doc.split_by_ranges(&ranges)
    .write_named_files(&output_paths)?;
5

Split into in-memory buffers

If you need to serve the split files over HTTP without touching disk, use to_bytes_vec() instead.

rust
let buffers: Vec<Vec<u8>> = doc
    .split_by_ranges(&ranges)
    .to_bytes_vec()?;

for (i, buf) in buffers.iter().enumerate() {
    println!("Segment {}: {} bytes", i + 1, buf.len());
}

Notes and tips

  • Page indices are 1-based. Passing 0 returns an error.
  • Ranges that extend past the last page are clamped to the last page automatically.
  • Bookmarks pointing to pages outside a range are dropped in that output file.
  • AcroForm fields on pages that fall within a range are included in the corresponding output file.

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