使用docxtemplater-image-module-free插入粘贴图片至docx遇namespaceURI错误求助
解决docxtemplater-image-module-free的namespaceURI只读错误
问题根源
你遇到的TypeError: Cannot set property namespaceURI of #<Element> which has only a getter错误,是因为docxtemplater-image-module-free旧版本会尝试修改DOM元素的只读属性namespaceURI,而现代浏览器严格限制了该属性的修改权限。另外,直接传递粘贴的图片DOM元素给图片模块也不符合要求——模块需要的是图片的原始二进制数据或base64编码,而非DOM节点。
修复步骤及完整代码示例
1. 引入兼容版本的依赖
使用CDN引入适配浏览器环境的依赖包:
<script src="https://unpkg.com/docxtemplater@3.37.10/build/docxtemplater.js"></script> <script src="https://unpkg.com/pizzip@3.1.4/dist/pizzip.js"></script> <script src="https://unpkg.com/pizzip@3.1.4/dist/pizzip-utils.js"></script> <script src="https://unpkg.com/docxtemplater-image-module-free@1.1.1/index.js"></script>
2. HTML结构
<div> <h3>粘贴图片到下方区域</h3> <div id="pasteArea" style="width: 500px; height: 300px; border: 1px solid #ccc; padding: 10px;"></div> <button id="generateBtn" style="margin-top: 10px;">生成DOCX</button> </div>
3. JavaScript核心逻辑
// 存储粘贴的图片数据(含base64和尺寸) let pastedImageData = null; // 监听粘贴事件 document.getElementById('pasteArea').addEventListener('paste', async (e) => { e.preventDefault(); const items = e.clipboardData.items; for (const item of items) { if (item.type.startsWith('image/')) { const blob = item.getAsFile(); // 把Blob转成base64并获取图片尺寸 const [base64, width, height] = await getImageInfo(blob); pastedImageData = { src: base64, width, height }; // 显示预览 const img = document.createElement('img'); img.src = base64; img.style.maxWidth = '100%'; document.getElementById('pasteArea').appendChild(img); break; } } }); // 辅助函数:获取图片base64和尺寸 function getImageInfo(blob) { return new Promise((resolve) => { const reader = new FileReader(); reader.onload = (e) => { const img = new Image(); img.onload = () => resolve([e.target.result, img.width, img.height]); img.src = e.target.result; }; reader.readAsDataURL(blob); }); } // 生成DOCX按钮事件 document.getElementById('generateBtn').addEventListener('click', async () => { if (!pastedImageData) { alert('请先粘贴图片'); return; } // 加载模板文件(需提前准备好template.docx,内含{image}占位标签) const response = await fetch('template.docx'); const content = await response.arrayBuffer(); const zip = new PizZip(content); // 配置图片模块 const imageModule = new ImageModule({ getImage(tag) { // 将base64转为模块需要的ArrayBuffer const base64Raw = tag.src.split(',')[1]; return PizZipUtils.base64ToArrayBuffer(base64Raw); }, getSize() { // 返回图片原始尺寸,也可自定义固定值如[300, 200] return [pastedImageData.width, pastedImageData.height]; } }); try { const doc = new docxtemplater(zip, { modules: [imageModule] }); doc.render({ image: pastedImageData }); // 生成并下载文件 const outBlob = doc.getZip().generate({ type: 'blob', mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); const link = document.createElement('a'); link.href = URL.createObjectURL(outBlob); link.download = 'result.docx'; link.click(); URL.revokeObjectURL(link.href); } catch (err) { console.error('生成失败:', err); alert('生成出错,请查看控制台日志'); } });
关键修复点
- 不再传递DOM元素:粘贴图片后先转为base64数据,避免模块直接操作DOM节点触发只读属性错误。
- 适配模块数据要求:
getImage回调返回模块需要的ArrayBuffer格式数据,而非原始base64字符串。 - 提前获取尺寸:在粘贴阶段就拿到图片宽高,避免在
getSize中异步处理引发的问题。
模板文件要求
你的template.docx模板中需要包含图片占位标签,比如:
{image}
如果需要自定义图片大小,可使用带参数的标签:
{image width=300 height=200}
内容的提问来源于stack exchange,提问作者Hansen Zhao
相关产品推荐
相关产品推荐

