在 Word 文档中处理图片是日常办公开发中最常见的需求之一,无论是为合同模板添加公司 Logo、清理文档中残留的占位图片,还是批量替换报告里的印章与图标,图片的动态操作都能让文档内容随业务数据同步更新。Spire.Doc for JavaScript 基于 WebAssembly 在浏览器端直接完成 Word 文档的图片处理,通过虚拟文件系统(VFS)管理字体、文档与图片资源,无需后端服务支持。
本文介绍三个核心功能点:
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript。以下示例默认已安装 Spire.Doc 并完成 WebAssembly 模块初始化。
在Word文档中添加图片
添加图片的核心流程分为三个阶段:首先通过 FetchFileToVFS 将字体文件、目标 Word 文档和待插入的图片文件载入 WASM 虚拟文件系统;然后实例化 Document 加载文件,获取目标节后创建 DocPicture 对象,通过 LoadImage 载入图片并设置位置、尺寸与文字环绕方式,再用 ChildObjects.Insert 将图片插入到指定段落的指定位置;最后将文档保存并从 VFS 读取生成的文件,封装为 Blob 后触发浏览器下载。
function App() {
const insertImage = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将输入文档载入 VFS
const inputFileName = "BlankTemplate.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// 将待插入的图片文件载入 VFS
const inputImgFileName = "Word.png";
await window.spire.FetchFileToVFS(inputImgFileName, "", `${process.env.PUBLIC_URL}static/data/`);
// 加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 获取第一节
let section = doc.Sections.get_Item(0);
// 添加标题段落
let paragraph = section.AddParagraph();
paragraph.AppendText("该示例演示了如何将图片插入到文档中。");
paragraph.ApplyStyle({ builtinStyle: docModule.BuiltinStyle.Heading2 });
// 新增一个用于承载图片的段落
paragraph = section.AddParagraph();
paragraph.AppendText("这是一张图片。");
// 创建图片对象并载入图片文件
let picture = new docModule.DocPicture(doc);
picture.LoadImage({ imgFile: inputImgFileName });
// 设置图片的位置
picture.HorizontalPosition = 50.0;
picture.VerticalPosition = 60.0;
// 设置图片的尺寸
picture.Width = 200;
picture.Height = 200;
// 设置图片的文字环绕方式
picture.TextWrappingStyle = docModule.TextWrappingStyle.Through;
// 将图片插入到段落的开头(索引 0)
paragraph.ChildObjects.Insert(0, picture);
// 保存文档
const outputFileName = "插入图片.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx });
// 释放资源
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
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>插入图片到Word文档</h1>
<button onClick={insertImage}>
生成
</button>
</div>
);
}
export default App;
上述代码通过 DocPicture 载入图片,设置其绝对位置为 (50, 60)、尺寸为 200×200,并采用四周环绕方式,最后插入到第二个段落的开头,生成的 Word 文档效果如下:

删除Word文档中的图片
删除图片的核心流程同样分为三个阶段:首先通过 FetchFileToVFS 将字体文件和待处理的 Word 文档载入 WASM 虚拟文件系统;然后实例化 Document 加载文件,逐层遍历文档中的节、段落以及段落内的子对象,通过 DocumentObjectType.Picture 判断对象是否为图片,若是则调用 ChildObjects.Remove 将其从段落中移除;最后保存文档并从 VFS 读取生成的文件,封装为 Blob 后触发浏览器下载。
function App() {
const RemoveImage = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将输入文档载入 VFS
const inputFileName = "ImageTemplate.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// 加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
let removedCount = 0;
// 遍历所有节与段落,删除段落中的图片
for (let i = 0; i < doc.Sections.Count; i++) {
let sec = doc.Sections.get_Item(i);
for (let j = 0; j < sec.Paragraphs.Count; j++) {
let para = sec.Paragraphs.get_Item(j);
// 收集段落中的所有图片对象
let pictures = [];
for (let k = 0; k < para.ChildObjects.Count; k++) {
let docObj = para.ChildObjects.get_Item(k);
if (docObj.DocumentObjectType == docModule.DocumentObjectType.Picture) {
pictures.push(docObj);
}
}
// 逐个移除段落中的图片
for (let m = 0; m < pictures.length; m++) {
para.ChildObjects.Remove(pictures[m]);
removedCount++;
}
}
}
// 保存文档
const outputFileName = "删除图片.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx });
// 释放资源
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
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>从Word文档中删除图片</h1>
<button onClick={RemoveImage}>
生成
</button>
</div>
);
}
export default App;
上述代码遍历文档结构并移除所有图片对象,段落中的文字内容与格式保持不变,生成的 Word 文档效果如下:

替换Word文档中的图片
替换图片可以看作是删除与添加的组合操作,核心流程分为三个阶段:首先通过 FetchFileToVFS 将字体文件、目标 Word 文档和新图片文件载入 WASM 虚拟文件系统;然后遍历节与段落,定位其中的图片对象并记录其在段落中的索引、原始尺寸与文字环绕方式,调用 ChildObjects.Remove 移除旧图片后,创建新的 DocPicture 并以相同参数在原索引位置插入;最后保存文档并从 VFS 读取生成的文件,封装为 Blob 后触发浏览器下载。
function App() {
const ReplaceImage = async () => {
const docModule = window.wasmModule?.spiredoc;
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 将输入文档载入 VFS
const inputFileName = "ImageTemplate.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// 将替换后的新图片载入 VFS
const inputImgFileName = "NewLogo.png";
await window.spire.FetchFileToVFS(inputImgFileName, "", `${process.env.PUBLIC_URL}/static/data/`);
// 加载文档
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// 遍历所有节与段落,将段落中的图片替换为新图片
for (let i = 0; i < doc.Sections.Count; i++) {
let sec = doc.Sections.get_Item(i);
for (let j = 0; j < sec.Paragraphs.Count; j++) {
let para = sec.Paragraphs.get_Item(j);
// 收集段落中的图片对象及其在 ChildObjects 中的索引
let pictures = [];
for (let k = 0; k < para.ChildObjects.Count; k++) {
let docObj = para.ChildObjects.get_Item(k);
if (docObj.DocumentObjectType == docModule.DocumentObjectType.Picture) {
pictures.push({ index: k, picture: docObj });
}
}
// 倒序遍历,避免移除对象后索引发生偏移
for (let m = pictures.length - 1; m >= 0; m--) {
let index = pictures[m].index;
let picture = pictures[m].picture;
// 记录原图片的尺寸与文字环绕方式
let width = picture.Width;
let height = picture.Height;
let wrappingStyle = picture.TextWrappingStyle;
// 移除原图片
para.ChildObjects.Remove(picture);
// 创建新图片并沿用原图片的尺寸与环绕方式
let newPicture = new docModule.DocPicture(doc);
newPicture.LoadImage({ imgFile: inputImgFileName });
newPicture.Width = width;
newPicture.Height = height;
newPicture.TextWrappingStyle = wrappingStyle;
// 在原索引位置插入新图片
para.ChildObjects.Insert(index, newPicture);
}
}
}
// 保存文档
const outputFileName = "更新图片.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx });
// 释放资源
doc.Dispose();
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
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>替换Word文档中的图片</h1>
<button onClick={ReplaceImage}>
生成
</button>
</div>
);
}
export default App;
上述代码在移除原图片的同时,将新图片插入到原图片所在的索引位置,并沿用其尺寸与环绕方式,因此替换后的文档版式与替换前完全一致,生成的 Word 文档效果如下:

常见问题
图片插入后不显示,或提示找不到图片文件
原因:图片文件未载入 WASM 虚拟文件系统,或 FetchFileToVFS 的加载路径与实际文件位置不一致,导致 LoadImage 无法从 VFS 中读取图片数据。
解决:插入图片前先通过 FetchFileToVFS 将图片载入 VFS,并确保目标文件名与 LoadImage 传入的文件名保持一致:
await window.spire.FetchFileToVFS(
'Word.png', '', `${process.env.PUBLIC_URL}static/data/`
);
let picture = new wasmModule.DocPicture(doc);
picture.LoadImage({ imgFile: 'Word.png' });
删除或替换图片后仍有残留,或图片位置发生偏移
原因:ChildObjects.Remove 会使后续子对象的索引整体前移,若在遍历过程中一边读取 ChildObjects.Count 一边移除,会跳过部分图片;替换时若直接使用移除后的新索引插入,也会导致图片插入到错误的位置。
解决:先一次性收集段落中的图片对象及其原始索引,再倒序遍历处理,插入新图片时沿用记录下来的原始索引:
// 先收集图片及其索引
pictures.push({ index: k, picture: docObj });
// 再倒序遍历,移除后以原索引插回新图片
for (let m = pictures.length - 1; m >= 0; m--) {
para.ChildObjects.Remove(pictures[m].picture);
para.ChildObjects.Insert(pictures[m].index, newPicture);
}
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







