How to Split PDF Files in the Browser with Vue 3 and pdf-lib

javascript dev.to

Splitting a PDF into multiple files requires careful handling of page ranges and document structure.

Here's how to build a browser-based PDF split tool with Vue 3 and pdf-lib.

The challenge: Flexible page splitting

PDF splitting involves:

  1. Loading the source PDF
  2. Understanding page structure and count
  3. Dividing pages based on user criteria
  4. Creating separate PDFs for each split

The stack

  • Vue 3 with Composition API
  • pdf-lib for PDF manipulation
  • JSZip for ZIP bundling
  • Vite for bundling

The core implementation

<script setup lang="ts">
import { ref } from 'vue'
import { PDFDocument } from 'pdf-lib'
import JSZip from 'jszip'

const file = ref<File | null>(null)
const totalPages = ref(0)
const splitMethod = ref<'range' | 'every'>('range')
const startPage = ref(1)
const endPage = ref(1)
const everyNPages = ref(10)
const splitting = ref(false)
const results = ref<Blob[]>([])

async function handleFile(e: Event) {
  const input = e.target as HTMLInputElement
  if (!input.files?.[0]) return
  file.value = input.files[0]

  const arrayBuffer = await file.value.arrayBuffer()
  const pdfDoc = await PDFDocument.load(arrayBuffer)
  totalPages.value = pdfDoc.getPageCount()
}

async function splitPdf() {
  if (!file.value) return
  splitting.value = true

  const arrayBuffer = await file.value.arrayBuffer()
  const pdfDoc = await PDFDocument.load(arrayBuffer)

  if (splitMethod.value === 'range') {
    const start = Math.max(1, startPage.value - 1)
    const end = Math.min(totalPages.value, endPage.value - 1)
    const pagesToCopy = Array.from({ length: end - start + 1 }, (_, i) => start + i)

    const newPdf = await PDFDocument.create()
    const copiedPages = await newPdf.copyPages(pdfDoc, pagesToCopy)
    copiedPages.forEach(page => newPdf.addPage(page))

    results.value = [await newPdf.save()]
  } else {
    // Split every N pages
    const chunks = []
    for (let i = 0; i < totalPages.value; i += everyNPages.value) {
      const chunkPages = Array.from(
        { length: Math.min(everyNPages.value, totalPages.value - i) },
        (_, j) => i + j
      )
      chunks.push(chunkPages)
    }

    results.value = await Promise.all(
      chunks.map(async (pageIndices) => {
        const newPdf = await PDFDocument.create()
        const copiedPages = await newPdf.copyPages(pdfDoc, pageIndices)
        copiedPages.forEach(page => newPdf.addPage(page))
        return await newPdf.save()
      })
    )
  }

  splitting.value = false
}
</script>
Enter fullscreen mode Exit fullscreen mode

Key implementation details

1. Page indexing

pdf-lib uses zero-based indexing internally, but users expect one-based:

const start = Math.max(1, startPage.value - 1) // Convert to zero-based
Enter fullscreen mode Exit fullscreen mode

2. Range validation

Ensure page ranges are within valid bounds:

const end = Math.min(totalPages.value, endPage.value - 1)
Enter fullscreen mode Exit fullscreen mode

3. ZIP bundling for multiple splits

When splitting into many files, bundle them into a ZIP:

const zip = new JSZip()
results.value.forEach((blob, i) => {
  zip.file(`page-${i + 1}.pdf`, blob)
})
const zipBlob = await zip.generateAsync({ type: 'blob' })
Enter fullscreen mode Exit fullscreen mode

4. Progress tracking

For large PDFs, show progress during splitting:

// Use async/await with small delays for UI updates
for (const chunk of chunks) {
  await processChunk(chunk)
  progress.value = (i + 1) / chunks.length
}
Enter fullscreen mode Exit fullscreen mode

Limitations

No interactive page selection

Users must specify ranges, not click individual pages.

Solution: Add a visual page selector UI.

Single file per operation

Can only split one PDF at a time.

Solution: Add batch processing support.

Memory constraints

Large PDFs may exhaust browser memory during splitting.

Solution: Process in smaller chunks and show progress.

Summary

Building a browser-based PDF split tool involves:

  1. Using pdf-lib to load and analyze PDFs
  2. Providing flexible split options (range or N pages)
  3. Creating new PDFs from page subsets
  4. Offering ZIP download for multiple splits

Try it at en.sotool.top/split.

Source: dev.to

arrow_back Back to Tutorials