Extract one or more page ranges from a PDF and write each range to a separate file. Useful for splitting chapters, invoices, or reports.
use pdfluent::PdfDocument;
fn main() -> pdfluent::Result<()> {
let doc = PdfDocument::open("report.pdf")?;
for (i, page) in doc.split_pages()?.into_iter().enumerate() {
page.save(format!("page-{}.pdf", i + 1))?;
}
Ok(())
}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.
use pdfluent::PdfDocument;
let doc = PdfDocument::open("quarterly_report.pdf")?;
println!("Source has {} pages", doc.page_count());Create PageRange values for each segment. Pages are 1-indexed. Ranges can overlap if you need the same page in multiple output files.
// Ranges to extract (0-based, end-exclusive)
let ranges = [0..5usize, 5..18, 18..22];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.
for (i, range) in ranges.iter().enumerate() {
doc.extract_pages(range.clone())?.save(format!("segment_{}.pdf", i + 1))?;
}
// Produces: segment_1.pdf, segment_2.pdf, segment_3.pdfWhen you need specific filenames, pass a slice of paths with the same length as the ranges slice.
let names = ["cover.pdf", "body.pdf", "appendix.pdf"];
for (range, name) in ranges.iter().zip(names) {
doc.extract_pages(range.clone())?.save(name)?;
}If you need to serve the split files over HTTP without touching disk, use to_bytes_vec() instead.
for (i, range) in ranges.iter().enumerate() {
let bytes = doc.extract_pages(range.clone())?.to_bytes()?;
println!("Segment {}: {} bytes", i + 1, bytes.len());
}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.