All PDF processing happens in your browser. Your files are never uploaded to a server.
(function() {
window.pdfMerger = function() {
return {
pdfFiles: [],
isDragging: false,
isProcessing: false,
mergedPdfUrl: null,
sortable: null,
status: {
show: false,
type: ‘info’, // info, processing, success, error
message: ”,
details: ”,
progress: 0,
icon: ‘fas fa-info-circle text-blue-500’
},
get statusClasses() {
return {
‘bg-blue-50’: this.status.type === ‘info’,
‘bg-yellow-50’: this.status.type === ‘processing’,
‘bg-green-50’: this.status.type === ‘success’,
‘bg-red-50’: this.status.type === ‘error’
};
},
init() {
this.$nextTick(() => {
this.setupSortable();
});
},
setupSortable() {
if (this.$refs.filesList) {
this.sortable = new Sortable(this.$refs.filesList, {
animation: 150,
ghostClass: ‘bg-blue-50’,
onEnd: (evt) => {
const itemEl = evt.item;
const oldIndex = evt.oldIndex;
const newIndex = evt.newIndex;
// Update the files array
if (oldIndex !== newIndex) {
const item = this.pdfFiles.splice(oldIndex, 1)[0];
this.pdfFiles.splice(newIndex, 0, item);
}
}
});
}
},
handleFileDrop(e) {
this.isDragging = false;
const files = Array.from(e.dataTransfer.files).filter(file => file.type === ‘application/pdf’);
if (files.length === 0) {
this.showStatus(‘error’, ‘Invalid Files’, ‘Please select only PDF files.’);
return;
}
this.addFiles(files);
},
handleFileSelect(e) {
const files = Array.from(e.target.files).filter(file => file.type === ‘application/pdf’);
if (files.length === 0) {
this.showStatus(‘error’, ‘Invalid Files’, ‘Please select only PDF files.’);
return;
}
this.addFiles(files);
// Reset the input to allow selecting the same file again
e.target.value = ”;
},
async addFiles(files) {
for (const file of files) {
// Create a placeholder entry
const pdfFile = {
file: file,
name: file.name,
size: file.size,
preview: null
};
this.pdfFiles.push(pdfFile);
// Generate thumbnail asynchronously
this.generatePdfThumbnail(file).then(thumbnail => {
const index = this.pdfFiles.findIndex(f => f.file === file);
if (index !== -1) {
this.pdfFiles[index].preview = thumbnail;
}
}).catch(error => {
console.error(‘Error generating thumbnail:’, error);
});
}
// Re-initialize Sortable if needed
this.$nextTick(() => {
if (this.sortable) {
this.sortable.destroy();
}
this.setupSortable();
});
},
async generatePdfThumbnail(file) {
try {
const arrayBuffer = await this.readFileAsArrayBuffer(file);
const pdfDoc = await PDFLib.PDFDocument.load(arrayBuffer);
if (pdfDoc.getPageCount() > 0) {
const firstPage = pdfDoc.getPages()[0];
const pngImage = await firstPage.toPng({ scale: 0.5 });
return URL.createObjectURL(new Blob([pngImage], { type: ‘image/png’ }));
}
} catch (error) {
console.error(‘Error generating PDF thumbnail:’, error);
return null;
}
},
readFileAsArrayBuffer(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
},
removeFile(index) {
this.pdfFiles.splice(index, 1);
},
clearAllFiles() {
this.pdfFiles = [];
if (this.mergedPdfUrl) {
URL.revokeObjectURL(this.mergedPdfUrl);
this.mergedPdfUrl = null;
}
this.closeStatus();
},
formatFileSize(bytes) {
if (bytes === 0) return ‘0 Bytes’;
const k = 1024;
const sizes = [‘Bytes’, ‘KB’, ‘MB’, ‘GB’];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ‘ ‘ + sizes[i];
},
async mergePDFs() {
if (this.pdfFiles.length < 2) {
this.showStatus('error', 'Not Enough Files', 'You need at least 2 PDF files to merge.');
return;
}
try {
this.isProcessing = true;
this.showStatus('processing', 'Merging PDFs', 'Processing your files… This may take a moment.', 0);
// Create a new PDF document
const mergedPdf = await PDFLib.PDFDocument.create();
for (let i = 0; i setTimeout(resolve, 50));
// Get the file
const file = this.pdfFiles[i].file;
const buffer = await this.readFileAsArrayBuffer(file);
// Load the PDF
const pdf = await PDFLib.PDFDocument.load(buffer);
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
// Add all pages to the merged PDF
pages.forEach(page => {
mergedPdf.addPage(page);
});
}
// Update status to indicate saving
this.updateStatus(‘processing’, ‘Almost Done’, ‘Saving your merged PDF…’, 95);
// Save the merged PDF
const mergedPdfBytes = await mergedPdf.save();
// Convert to Blob and create URL
const blob = new Blob([mergedPdfBytes], { type: ‘application/pdf’ });
if (this.mergedPdfUrl) {
URL.revokeObjectURL(this.mergedPdfUrl);
}
this.mergedPdfUrl = URL.createObjectURL(blob);
// Show success status
this.showStatus(‘success’, ‘Merge Completed’, `Successfully merged ${this.pdfFiles.length} PDF files.`, 100);
} catch (error) {
console.error(‘Error merging PDFs:’, error);
this.showStatus(‘error’, ‘Merge Failed’, ‘An error occurred while merging your PDFs. Please try again.’);
} finally {
this.isProcessing = false;
}
},
downloadMergedPDF() {
if (!this.mergedPdfUrl) return;
const a = document.createElement(‘a’);
a.href = this.mergedPdfUrl;
a.download = ‘merged-document.pdf’;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
},
showStatus(type, message, details, progress = 0) {
this.status.show = true;
this.status.type = type;
this.status.message = message;
this.status.details = details;
this.status.progress = progress;
// Set the appropriate icon
switch (type) {
case ‘info’:
this.status.icon = ‘fas fa-info-circle text-blue-500’;
break;
case ‘processing’:
this.status.icon = ‘fas fa-spinner fa-spin text-yellow-500’;
break;
case ‘success’:
this.status.icon = ‘fas fa-check-circle text-green-500’;
break;
case ‘error’:
this.status.icon = ‘fas fa-exclamation-circle text-red-500’;
break;
}
},
updateStatus(type, message, details, progress) {
this.status.type = type;
this.status.message = message;
this.status.details = details;
this.status.progress = progress;
// Set the appropriate icon
switch (type) {
case ‘info’:
this.status.icon = ‘fas fa-info-circle text-blue-500’;
break;
case ‘processing’:
this.status.icon = ‘fas fa-spinner fa-spin text-yellow-500’;
break;
case ‘success’:
this.status.icon = ‘fas fa-check-circle text-green-500’;
break;
case ‘error’:
this.status.icon = ‘fas fa-exclamation-circle text-red-500’;
break;
}
},
closeStatus() {
this.status.show = false;
}
};
};
})();
How to Use PDF Merger Easily
Merging multiple PDF files into one document is simple when you use the right tool. With a reliablePDF Merger, you can combine files quickly without installing any software. This step-by-step guide will help you use a PDF Merger efficiently.
Step 1: Choose a Trusted Online PDF Merger
Start by selecting a secure and trusted online tool. Look for a website that offers free access, supports multiple files, and ensures data privacy. A good PDF Merger will work directly in your browser and require no downloads.
Step 2: Upload Your PDF Files
Click the “Upload” or “Choose Files” button to add the PDF documents you want to combine. Most tools let you upload files from your computer, cloud storage, or even drag and drop them directly onto the page.
Step 3: Arrange the File Order
After uploading, arrange your files in the desired sequence. Simply drag each file into position so that the merged PDF reads in the correct order. This step is important because the final document will follow the sequence you set.
Step 4: Merge and Download
Once your files are in the correct order, click the “Merge” or “Combine” button. The tool will process the files within seconds. Then, download the merged document to your device or save it directly to your cloud storage.
Step 5: Check and Share
Open the merged file to make sure everything looks correct. If you need changes, you can repeat the process until you are satisfied. After that, share the file with others via email, messaging apps, or upload it to your website.
Why Use a PDF Merger?
A PDF Merger saves time, reduces clutter, and makes sharing information easier. Whether you are combining contracts, reports, or study materials, merging files into one document keeps everything organized and professional.
By following these steps, you can merge PDF files quickly and securely. With a good online tool, the process takes only a few minutes and works from any device.