Splitting PDF files in the browser requires careful handling of page ranges and memory management. Here's how to build a browser-based PDF split tool with Vue 3 and pdf-lib.
The challenge: Managing page ranges
When splitting PDFs, you need to:
- Support multiple split modes (by range, by count, by selection)
- Handle large PDFs without memory issues
- Provide clear preview of split results
- Preserve document structure where possible
The stack
- Vue 3 with Composition API
- pdf-lib for PDF manipulation
- Vite for bundling
The core implementation
<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument } from 'pdf-lib'
const file = ref<File | null>(null)
const splitMode = ref<'range' | 'count' | 'custom'>('range')
const splitRanges = ref<{ start: number; end: number }[]>([])
const splitting = ref(false)
const results = ref<Array<{ name: string; data: Uint8Array }>>([])
async function splitPdf() {
if (!file.value) return
splitting.value = true
const arrayBuffer = await file.value.arrayBuffer()
const sourcePdf = await PDFDocument.load(arrayBuffer)
const totalPages = sourcePdf.getPageCount()
results.value = []
for (const range of splitRanges.value) {
const newPdf = await PDFDocument.create()
const indices = Array.from(
{ length: range.end - range.start + 1 },
(_, i) => range.start + i
)
const pages = await newPdf.copyPages(sourcePdf, indices)
pages.forEach(page => newPdf.addPage(page))
results.value.push({
name: `split_${range.start + 1}-${range.end + 1}.pdf`,
data: await newPdf.save(),
})
}
splitting.value = false
}
</script>
Key implementation details
1. Page index conversion
pdf-lib uses 0-based indexing, but users think in 1-based:
const indices = Array.from(
{ length: range.end - range.start + 1 },
(_, i) => range.start + i // Convert 1-based to 0-based
)
2. Copying pages between PDFs
const pages = await newPdf.copyPages(sourcePdf, indices)
pages.forEach(page => newPdf.addPage(page))
3. Multiple output files
Store results as named Uint8Array pairs:
results.value.push({
name: `split_${start}-${end}.pdf`,
data: await newPdf.save(),
})
4. Memory management
Process pages sequentially to avoid memory issues:
for (const range of splitRanges.value) {
const newPdf = await PDFDocument.create()
// ... process range ...
results.value.push({ name, data })
}
Limitations
No undo
Once split, original pages are distributed across files.
Solution: Always keep the original PDF.
Large files
Very large PDFs may cause memory issues when loading all pages.
Solution: Process in smaller batches.
Password-protected PDFs
Encrypted PDFs cannot be split without the password.
Solution: Remove encryption first.
Summary
Building a browser-based PDF split tool involves:
- Loading the source PDF with pdf-lib
- Validating page ranges (1-based to 0-based)
- Copying pages to new PDFDocument instances
- Returning multiple download links
Try it at en.sotool.top/split.
Top comments (0)