Combining multiple PDFs into one seems simple, but there are important considerations around file ordering and memory management. Here's how to build a browser-based PDF merge tool with Vue 3 and pdf-lib.
The challenge: Managing multiple documents
When merging PDFs, you need to:
- Load multiple PDF files in the browser
- Display thumbnails for ordering
- Merge page streams without losing content
- Handle large files without crashing
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 files = ref<File[]>([])
const merging = ref(false)
const result = ref<Uint8Array | null>(null)
async function mergePdfs() {
if (files.value.length === 0) return
merging.value = true
const mergedPdf = await PDFDocument.create()
for (const file of files.value) {
const arrayBuffer = await file.arrayBuffer()
const pdf = await PDFDocument.load(arrayBuffer)
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices())
pages.forEach(page => mergedPdf.addPage(page))
}
result.value = await mergedPdf.save()
merging.value = false
}
function reorderFiles(fromIndex: number, toIndex: number) {
const updated = [...files.value]
const [removed] = updated.splice(fromIndex, 1)
updated.splice(toIndex, 0, removed)
files.value = updated
}
</script>
Key implementation details
1. Loading multiple PDFs
Use the File API to read each file as an ArrayBuffer:
const arrayBuffer = await file.arrayBuffer()
const pdf = await PDFDocument.load(arrayBuffer)
2. Copying pages between PDFs
pdf-lib requires explicit page copying:
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices())
pages.forEach(page => mergedPdf.addPage(page))
3. Drag-and-drop reordering
Implement a simple index-based reorder:
function reorderFiles(fromIndex: number, toIndex: number) {
const updated = [...files.value]
const [removed] = updated.splice(fromIndex, 1)
updated.splice(toIndex, 0, removed)
files.value = updated
}
4. Memory management
For large files, process sequentially:
for (const file of files.value) {
const pdf = await PDFDocument.load(await file.arrayBuffer())
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices())
pages.forEach(page => mergedPdf.addPage(page))
}
Limitations
No undo
Once merged, files cannot be separated.
Solution: Always keep backups of original files.
Large files
Very large PDFs may cause memory issues in the browser.
Solution: Process files in smaller batches or use Web Workers.
Password-protected PDFs
Encrypted PDFs cannot be merged without the password.
Solution: Remove encryption first.
Summary
Building a browser-based PDF merge tool involves:
- Loading multiple PDFs with the File API
- Copying pages between PDFDocument instances
- Providing drag-and-drop reordering
- Saving and downloading the merged result
Try it at en.sotool.top/merge.
Top comments (0)