PDF 里的超链接本该是最省事的一环——点一下就到,不用复制、不用手打。可到了要批量维护的时候,事情就反过来了:产品文档里的网址换了域名,得一处一处改;一份旧版说明书要对外发布,里面的外链得先清干净。这些活儿在桌面软件里要么靠手工点,要么根本做不了批量。
本文介绍用 Spire.PDF for JavaScript 实现修改和删除超链接。它基于 WebAssembly 在浏览器端直接加载、修改与保存 PDF 文档,全过程在本地完成,通过虚拟文件系统(VFS)读写文件,无需后端配合。
本文介绍两个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.PDF for JavaScript。以下示例默认已安装 Spire.PDF 并完成 WebAssembly 模块初始化。
修改超链接
文档里的网址换了域名时,一处一处重设很费事。已有的链接注解可以用 PdfUriAnnotationWidget 读写,它的 Uri 属性就是链接的目标地址。逐页遍历注解集合、把匹配到的对象改掉,就能批量换链。
function App() {
const updateHyperlinks = 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);
// 新的链接地址
const newUrl = 'https://www.e-iceblue.com/Introduce/pdf-for-javascript.html';
// 逐页遍历注解,改写其中的 URI 链接
for (let i = 0; i < doc.Pages.Count; i++) {
const page = doc.Pages.get_Item(i);
for (let j = 0; j < page.Annotations.Count; j++) {
const annotation = page.Annotations.get_Item(j);
// 只处理链接注解,其它类型的注解原样保留
if (annotation instanceof pdfModule.PdfUriAnnotationWidget) {
annotation.Uri = newUrl;
}
}
}
// 保存生成的文档
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 downloadUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(downloadUrl);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>修改超链接</h1>
<button onClick={updateHyperlinks}>
开始修改
</button>
</div>
);
}
export default App;
文档中原有的三个超链接已指向新地址:

删除超链接
删除超链接同样是遍历注解集合,匹配到链接注解后 Remove。区别在于要先收集、后删除:在遍历的同时删除会让集合前移,循环会跳过紧跟在被删项后面的那一条。
function App() {
const deleteHyperlinks = 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);
// 先把所有链接注解收集起来
const links = [];
for (let i = 0; i < doc.Pages.Count; i++) {
const page = doc.Pages.get_Item(i);
for (let j = 0; j < page.Annotations.Count; j++) {
const annotation = page.Annotations.get_Item(j);
if (annotation instanceof pdfModule.PdfUriAnnotationWidget) {
links.push({ page, annotation });
}
}
}
// 收集完成后再统一移除
for (const link of links) {
link.page.Annotations.Remove(link.annotation);
}
// 保存生成的文档
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 downloadUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = downloadUrl;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(downloadUrl);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>删除超链接</h1>
<button onClick={deleteHyperlinks}>
开始删除
</button>
</div>
);
}
export default App;
文档中的超链接已被全部移除:

常见问题
改了 Uri,保存后地址却没变
原因:链接注解不止一类。Uri 属性只存在于 PdfUriAnnotationWidget 上。由 Word 导出、或用 Spire 的 PdfTextWebLink 生成的超链接是另一个类 PdfTextWebLinkAnnotationWidget,它的地址属性叫 Url。代码里只判断其中一个类,另一类就被整段跳过。
解决:两类都判断,各写各的属性:
if (annotation instanceof pdfModule.PdfUriAnnotationWidget) {
annotation.Uri = newUrl;
} else if (annotation instanceof pdfModule.PdfTextWebLinkAnnotationWidget) {
annotation.Url = newUrl;
}
循环里一边遍历一边删除,为什么只删掉一部分?
原因:page.Annotations 是可变的注解集合,删掉第 i 项之后,后面的注解会整体前移一位,而循环里的 i 照常自增,等于跳过了紧跟其后的那一条。一页上有几条链接,就会漏掉几条。
解决:先把待删的注解收集到数组,遍历结束后再统一移除:
const links = [];
// ……先遍历收集……
// 收集完成后再删除
for (const link of links) {
link.page.Annotations.Remove(link.annotation);
}
删除超链接会不会把批注一起删掉?
原因:page.Annotations 里不只有链接,文本框批注、弹窗(Popup)、表单域等都挂在同一个集合上。调用 Clear(),或者不加判断地整轮删除,会把这些内容一并清掉。
解决:只删链接类,其余注解原样保留:
if (annotation instanceof pdfModule.PdfUriAnnotationWidget) {
page.Annotations.Remove(annotation);
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







