PDF 文档以“页”为基本单位,阅读、打印、归档都按页展开。实际业务里经常需要在已有 PDF 上调整页面:为合同补入一页签署说明、在报告末尾追加一张汇总页,或者把材料中多余的一页删掉。这类操作若借助本地软件或服务端重排,就要来回导出、上传,流程繁琐。如果能在浏览器端直接完成增删页面,文档无需离开用户设备,处理链路会短很多。
Spire.PDF for JavaScript 基于 WebAssembly 在浏览器端直接加载、修改与保存 PDF 文档,通过虚拟文件系统(VFS)管理输入输出文件,无需后端服务支持。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
在 PDF 文档中添加页面
添加页面就是往 PdfPageCollection 集合里插一项。在指定位置插入使用 Pages.Insert(index),索引从 0 开始,插入点之后原有的页面会依次后移。这里把空白页放到第二页的位置,原有页面顺次后移,适合在文档中间补入新页。
function App() {
const addPageToPdf = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待处理的 PDF 文件载入 VFS
const inputFileName = '多页文档.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 在第二页位置插入一张空白页(索引从 0 开始,索引 1 对应第二页)
doc.Pages.Insert(1);
// 定义输出文件名并保存文档
const outputFileName = '插入页面结果.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加 PDF 页面</h1>
<button onClick={addPageToPdf}>
开始添加
</button>
</div>
);
}
export default App;
在第二页位置插入空白页后的 PDF 文档

在文档末尾添加空白页
Spire.PDF for JavaScript 还提供 Pages.Add() 方法,用于在文档末尾追加空白页。它默认采用 A4 页面尺寸,上下左右页边距均为 40 磅;需要时也可自定义页面尺寸与页边距。
function App() {
const appendPageToPdf = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待处理的 PDF 文件载入 VFS
const inputFileName = '多页文档.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 在文档末尾追加一页 A4 空白页,四边页边距均为 0
doc.Pages.Add(pdfModule.PdfPageSize.A4(), new pdfModule.PdfMargins(0.0, 0.0));
// 定义输出文件名并保存文档
const outputFileName = '末尾添加页面结果.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加空白页到文档末尾</h1>
<button onClick={appendPageToPdf}>
开始添加
</button>
</div>
);
}
export default App;
在文档末尾追加一页 A4 空白页后的 PDF 文档

在 PDF 文档中删除页面
删除页面同样围绕页面集合进行,Pages.RemoveAt(index) 按索引移除一页,索引从 0 开始,删除后其后页面的索引会整体前移一位。写删除逻辑前,最好先用 Pages.Count 确认当前页数,把索引控制在有效范围内。这里将样例文档的第二页移除,其余页面按原有顺序保留。
function App() {
const deletePageFromPdf = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待处理的 PDF 文件载入 VFS
const inputFileName = '多页文档.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载 PDF 文档
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 删除第二页(索引从 0 开始,索引 1 对应第二页)
doc.Pages.RemoveAt(1);
// 定义输出文件名并保存文档
const outputFileName = '删除页面结果.pdf';
doc.SaveToFile(outputFileName);
doc.Close();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>删除 PDF 页面</h1>
<button onClick={deletePageFromPdf}>
开始删除
</button>
</div>
);
}
export default App;
删除第二页后的 PDF 文档

常见问题
新增空白页时如何指定纸张大小与页边距
原因:Pages.Add 与 Pages.Insert 默认新建的是常规尺寸、默认页边距的空白页。若新页需要匹配特定的纸张规格或页边距,就要把尺寸与边距一并传入。
解决:纸张规格由 PdfPageSize 给出,如 PdfPageSize.A4()、PdfPageSize.A3();页边距用 PdfMargins 指定,两参数写法 new PdfMargins(0.0, 0.0) 表示上下与左右均为 0,需要分别控制四边时可传入具名参数:
// A4 纸张、四边页边距均为 0 的空白页
doc.Pages.Add(pdfModule.PdfPageSize.A4(), new pdfModule.PdfMargins(0.0, 0.0));
// 单独指定上下左右的页边距
doc.Pages.Add(pdfModule.PdfPageSize.A4(),
new pdfModule.PdfMargins({ left: 40, top: 40, right: 40, bottom: 40 }));
删除页面时为什么会提示索引越界
原因:RemoveAt(index) 的索引从 0 开始,有效范围是 0 到 Pages.Count - 1。若事先没有确认页数,传入等于或超过 Count 的值就会越界。
解决:删除前用 Pages.Count 核对页数,把索引限制在有效范围内。例如删除最后一页时,索引应取 Count - 1:
let total = doc.Pages.Count;
if (total > 0) {
// 删除最后一页
doc.Pages.RemoveAt(total - 1);
}
连续增删多个页面时要注意什么
原因:每插入或删除一页,其后所有页面的索引都会随之变化。若按固定索引从前往后连续删除,很容易删错页面——删掉一页后,原本记录的后续索引已经整体前移。
解决:Insert、Add 与 RemoveAt 一次只处理一页,重复调用即可完成批量操作。批量删除时从后往前进行,可以避免删除过程中索引错位:
// 从后往前删除,索引不会因前一次删除而偏移
for (let i = doc.Pages.Count - 1; i >= 3; i--) {
doc.Pages.RemoveAt(i);
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







