在日常开发中,PDF 处理是一个常见的需求。无论是合并多份合同、提取指定页面,还是在前端直接操作 PDF 文件,我们都希望在浏览器端就能完成,而不是依赖后端服务。
今天介绍一个轻量级的 JavaScript 库 ------ pdf-lib,它可以在浏览器和 Node.js 环境中对 PDF 进行各种操作,包括合并、拆分、旋转、填写表单等。
🚀 为什么选择 pdf-lib?
| 特性 | 说明 |
|---|---|
| 纯前端运行 | 无需后端,直接在浏览器中处理 PDF |
| 零依赖 | 不依赖原生插件或外部服务 |
| 功能丰富 | 支持合并、拆分、编辑、加密等 |
| TypeScript 支持 | 有完整的类型定义 |
| 体积小巧 | 压缩后约 100KB 左右 |
相比后端方案(如 Python 的 PyPDF2、Java 的 iText),pdf-lib 的优势在于用户体验更流畅------用户选择文件后秒级出结果,无需等待上传下载。
📦 安装与引入
npm 安装
vbnet
npm install pdf-lib
CDN 引入
xml
<script src="https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.min.js"></script>
基础用法
javascript
import { PDFDocument } from 'pdf-lib';
// 读取本地 PDF 文件
async function loadPdf(file) {
const arrayBuffer = await file.arrayBuffer();
const pdfDoc = await PDFDocument.load(arrayBuffer);
return pdfDoc;
}
🔗 实战一:PDF 合并
需求:用户上传多份 PDF,按顺序合并成一份文件。
ini
import { PDFDocument } from 'pdf-lib';
/**
* 合并多个 PDF 文件
* @param {File[]} files - 用户选择的 PDF 文件列表
* @returns {Promise<Uint8Array>} 合并后的 PDF 数据
*/
async function mergePdfs(files) {
// 创建一个新的空白 PDF 文档
const mergedPdf = await PDFDocument.create();
for (const file of files) {
const arrayBuffer = await file.arrayBuffer();
const pdf = await PDFDocument.load(arrayBuffer);
// 拷贝所有页面到新文档
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => mergedPdf.addPage(page));
}
// 保存为 Uint8Array
return await mergedPdf.save();
}
// 下载合并后的文件
async function downloadMergedPdf(files) {
const pdfBytes = await mergePdfs(files);
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'merged.pdf';
a.click();
URL.revokeObjectURL(url);
}
核心 API 解析
PDFDocument.create():创建空白 PDFPDFDocument.load(arrayBuffer):加载已有 PDFcopyPages(targetDoc, pageIndices):拷贝页面(注意是异步的)addPage(page):添加页面到文档
✂️ 实战二:PDF 拆分
需求:从大文件中提取指定页码范围,生成新的 PDF。
javascript
import { PDFDocument } from 'pdf-lib';
/**
* 提取 PDF 指定页面
* @param {File} file - 源 PDF 文件
* @param {number[]} pageIndices - 要提取的页码索引(从0开始)
* @returns {Promise<Uint8Array>}
*/
async function splitPdf(file, pageIndices) {
const arrayBuffer = await file.arrayBuffer();
const srcPdf = await PDFDocument.load(arrayBuffer);
// 创建新文档
const newPdf = await PDFDocument.create();
// 拷贝指定页面
const copiedPages = await newPdf.copyPages(srcPdf, pageIndices);
copiedPages.forEach((page) => newPdf.addPage(page));
return await newPdf.save();
}
// 使用示例:提取第 2-5 页(索引 1-4)
async function extractPages(file, startPage, endPage) {
const indices = [];
for (let i = startPage - 1; i < endPage; i++) {
indices.push(i);
}
return await splitPdf(file, indices);
}
进阶:按固定页数拆分
ini
/**
* 将 PDF 按每 N 页拆分成多个文件
*/
async function splitByPageCount(file, pagesPerFile) {
const arrayBuffer = await file.arrayBuffer();
const srcPdf = await PDFDocument.load(arrayBuffer);
const totalPages = srcPdf.getPageCount();
const results = [];
for (let i = 0; i < totalPages; i += pagesPerFile) {
const end = Math.min(i + pagesPerFile, totalPages);
const indices = Array.from({ length: end - i }, (_, j) => i + j);
const newPdf = await PDFDocument.create();
const copiedPages = await newPdf.copyPages(srcPdf, indices);
copiedPages.forEach((page) => newPdf.addPage(page));
results.push(await newPdf.save());
}
return results; // 返回多个 Uint8Array
}
🎨 一个简单的 UI 示例
把上面的代码封装成一个简单的网页工具:
xml
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>PDF 工具</title>
<script src="https://unpkg.com/pdf-lib@1.17.1/dist/pdf-lib.min.js"></script>
</head>
<body>
<h2>PDF 合并</h2>
<input type="file" id="mergeInput" multiple accept=".pdf">
<button onclick="handleMerge()">合并并下载</button>
<script>
const { PDFDocument } = PDFLib;
async function handleMerge() {
const files = document.getElementById('mergeInput').files;
if (files.length < 2) {
alert('请至少选择两个 PDF 文件');
return;
}
const mergedPdf = await PDFDocument.create();
for (const file of files) {
const bytes = await file.arrayBuffer();
const pdf = await PDFDocument.load(bytes);
const pages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
pages.forEach(p => mergedPdf.addPage(p));
}
const pdfBytes = await mergedPdf.save();
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'merged.pdf';
a.click();
URL.revokeObjectURL(url);
}
</script>
</body>
</html>
把上面代码保存为 .html 文件,用浏览器打开就能直接用。
⚠️ 注意事项
- 大文件性能:pdf-lib 适合处理几十 MB 以内的 PDF,如果是几百 MB 的扫描件,可能会有性能瓶颈
- 字体兼容:某些特殊字体嵌入的 PDF,合并后可能出现字体丢失
- 加密文件:受密码保护的 PDF 需要先解密才能处理
💡 不想写代码?
如果你只是想快速处理 PDF,不想搭建前端项目、写代码、调试兼容性问题,可以直接用现成的在线工具。

上面提到的合并、拆分功能,还有 PDF 转 Word、压缩等常用操作,这个在线工具集都覆盖了:
- ✅ 打开网页直接用,不用下载软件
- ✅ 无需注册登录
- ✅ 目前完全免费,没有页数限制
工具派:百度搜索:工具派,显示的第一个就是
当然,如果你是开发者,想要把 PDF 功能集成到自己的项目里,pdf-lib 仍然是一个非常值得考虑的选择。
📚 相关链接
有用的话欢迎点赞收藏,有相关的技术问题欢迎在评论区交流 👇