合同、标书这类多页文件外发前要盖骑缝章,为的是让每一页都带上印章残片——对方一旦抽换或重排过页,残片就对不上。纸质件可以整叠一盖,电子 PDF 没有对应的动作:把印章图片整枚贴上去,每页都是完整的章,起不到骑缝的作用。
本文介绍用 Spire.PDF for JavaScript 为多页合同添加骑缝章。它基于 WebAssembly 在浏览器端直接加载、修改与保存 PDF 文档,全过程在本地完成,通过虚拟文件系统(VFS)读写文件,无需后端配合。
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
添加骑缝章
骑缝章把一枚印章按页数切开,每页只落一片,翻页时各页残片能拼回完整印章。切片用 PdfTemplate 承载:模板的界框就是裁切范围,只要把印章在模板里逐页左移一个片宽,每页露出的就正好是自己那一片,再由 Canvas.DrawTemplate 落到页面右缘。
function App() {
const addCrossPageSeal = async () => {
// 获取 Spire.PDF WASM 模块
const pdfModule = window.wasmModule?.spirepdf;
// 检查模块是否就绪
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// 将待盖章的合同与印章图片载入 VFS
const inputFileName = 'Number.pdf';
const sealFileName = 'Seal.png';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
await window.spire.FetchFileToVFS(sealFileName, '', `${process.env.PUBLIC_URL}/data/`);
// 创建 PdfDocument 对象并加载合同
const doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// 载入印章图片;它的宽高是像素值,排版时按 1 像素 = 1 磅参与计算
const seal = pdfModule.PdfImage.FromFile(sealFileName);
// 印章整体缩放比例,以及缩放后的章宽、章高
const scale = 0.55;
const sealWidth = seal.Width * scale;
const sealHeight = seal.Height * scale;
// 按页数把印章等分,每页承载一片
const pageCount = doc.Pages.Count;
const stripWidth = sealWidth / pageCount;
// 逐页把印章的第 i 片贴到页面右缘
for (let i = 0; i < pageCount; i++) {
const page = doc.Pages.get_Item(i);
// 模板界框就是裁切范围:片宽 × 章高,刚好装下一片
const template = new pdfModule.PdfTemplate({ width: stripWidth, height: sealHeight });
template.Graphics.ScaleTransform(scale, scale);
// 每往后一页就把印章多左移一个片宽,于是模板里露出的是下一片
template.Graphics.DrawImage({ image: seal, x: -(i * seal.Width) / pageCount, y: 0 });
// 每一页都落在同一位置:页面右缘向内留 24 磅,垂直居中
const x = page.Canvas.ClientSize.Width - 24 - stripWidth;
const y = (page.Canvas.ClientSize.Height - sealHeight) / 2;
page.Canvas.DrawTemplate({ template: template, location: new pdfModule.PointF(x, y) });
}
// 保存到 VFS
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={addCrossPageSeal}>
开始盖章
</button>
</div>
);
}
export default App;
加盖骑缝章后的合同,每页右缘各有一片印章残片,翻到最后一页即为印章的右半部分:

常见问题
为什么每页只显示印章的一小段
原因:骑缝章本身就是按页等分切开的,每页只承载 印章宽度 / 页数 那一片。页数越多,每页上的残片越窄,这是设计使然——残片窄、位置固定,才能保证抽换单页后拼不回去。
解决:页数由文档决定,想让它更醒目,只能把整枚印章放大,残片会跟着变宽:
// 把 0.55 调大,例如 0.8,整章与每页残片一起变大
const scale = 0.8;
const sealWidth = seal.Width * scale;
印章盖得太大,把正文压住了
原因:PdfImage.Width 与 Height 给出的是像素值,不缩放就按 1 像素 = 1 磅落版。一张 400×400 像素的印章会占掉 400 磅宽,而 A4 页面只有 595 磅宽,自然会盖住正文。
解决:在模板里用 ScaleTransform 等比缩小,同时按同一个比例换算章宽、章高与片宽,三者必须同源,否则切片会与落点对不齐:
const scale = 0.55;
const sealWidth = seal.Width * scale;
const sealHeight = seal.Height * scale;
const stripWidth = sealWidth / pageCount;
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







