为什么 SuperDoc 只显示最后一张图片:DOCX 内部结构调查
I’m sorry, but I don’t have access to the full text of the article at the link you provided, so I can’t translate it for you. If you paste the content you’d like translated here, I’ll be happy to help.
症状
生成的报告包含多个属性图片,排列成网格。
| 编辑器中预期 | SuperDoc 中的实际结果 |
|---|---|
| 图片 1 → 插槽 1 | 插槽 1 → 最后一个图片 |
| 图片 2 → 插槽 2 | 插槽 2 → 最后一个图片 |
| 图片 3 → 插槽 3 | 插槽 3 → 最后一个图片 |
奇怪的是:
- Microsoft Word → 正确
- LibreOffice → 正确
- Google Docs → 正确
- SuperDoc 编辑器 → 错误
因此 DOCX 本身是有效的;问题出现在特定编辑器上。
环境
| 工具 | 版本 |
|---|---|
| SuperDoc | 1.16.x |
docx-templates | 4.15.0 |
| Node | 20.x |
图片是使用 docx-templates 循环插入的,并通过 docxUrl 加载到编辑器中。
首次检查:DOCX 是否损坏?
初始假设:DOCX 生成可能出现问题。
验证步骤
- 在 Word 中打开 – ✅
- 在 LibreOffice 中打开 – ✅
- 转换为 PDF – ✅
- 上传至 Google Docs – ✅
在所有地方均正确渲染,除编辑器内部外。
结论: 基本排除了 DOCX 损坏的可能。
深度调试方法
由于 DOCX 文件本质上是 ZIP 压缩包,我解压并检查了原始 XML:
word/document.xml
word/_rels/document.xml.rels
word/media/
目标是查看图像在内部是如何被引用的。
发现 1:非标准的关系 ID
通常 DOCX 使用类似 rId1、rId2、rId3 的关系 ID。
生成的 DOCX 中出现了基于哈希的 ID,例如:
执行的测试 – 将所有关系 ID 改为标准的 rId1、rId2 … 并更新引用。
结果: 编辑器行为未改变;所有图像槽仍然显示最后一张图像。
结论: 关系 ID 不是主要原因。
发现 2:媒体文件名
生成的文件名类似:
template_document.xml_img2073076884.jpg
而不是常见的 image1.jpg、image2.jpg。
执行的测试 – 将它们重命名为标准格式并更新引用。
结果: 在编辑器中仍然出现问题。
结论: 文件名约定不是导致问题的原因。
发现 3:表格中的图像?
怀疑表格单元格内的图像被扁平化或合并。
检查: 原始 XML 结构——图像已经位于独立的段落中,并未嵌套在复杂的表格绘图结构里。
结果: 未发现结构性问题。
发现 4:Base64 外部引用
将图像转换为 base64 编码的外部引用,以排除编辑器内部的媒体文件解析问题。
结果: 仍然出现故障——所有槽位仍显示最后一张图像。
结论: 问题出在编辑器对绘图节点身份的解释方式,而不是图像的存储或引用方式。
目前最有力的线索(未验证)
在检查每个图像的 drawing XML 时,出现了一个模式:
每个图像的 id="0"。
根据 OOXML 规范,此属性在文档内的每个 drawing 对象必须是 唯一的。
docx-templates 似乎为所有生成的图像分配了 id="0"。
工作假设: SuperDoc 使用 ProseMirror(或类似的引擎)进行渲染。如果解析器依赖 pic:cNvPr/@id 来区分 drawing 节点,重复的 ID 可能导致它将所有图像视为同一个节点,最后加载的图像会“赢得”每个槽位。
注意: 这只是一个假设,并非已确认的修复。下一步是对 docx-templates 的输出进行补丁,注入唯一的顺序 ID,进行干净的服务器重启,并验证结果。之前一次失败的测试是因为使用了旧的编译代码,服务器在重建后没有重新启动。
到目前为止已尝试的操作
| 尝试内容 | 结果 |
|---|---|
| 从表格中提取图像 | 未改变 |
将关系 ID 重命名为 rId1/rId2 | 未改变 |
将媒体文件名重命名为 image1.jpg | 未改变 |
| 将图像转换为 base64 外部引用 | 未改变 |
| 检查绘图 XML | 发现所有图像都有重复的 id="0" |
| 修补为唯一 ID | 尚未完全验证 |
当前状态
问题仍在调查中。
主要假设: 所有图像中重复的 pic:cNvPr/@id="0" 导致编辑器将它们折叠为单个节点。
后续步骤
- 向绘图 XML 注入唯一 ID。
- 完整重启服务器。
- 进行彻底验证(在 SuperDoc、Word、LibreOffice、Google Docs 中打开 DOCX)。
本次调试会话的经验教训
-
如果在 Word 中能正常工作,也可能是错误的
Word 会默默容忍许多 OOXML 违规。编辑器和转换器更为严格。不要假设 Word 的渲染等同于正确。 -
始终内部检查 DOCX
将 DOCX 当作 ZIP 文件处理。解压后检查 XML,搜索模式,验证结构——调试会快得多。 -
渲染引擎表现不同
| 工具 | 严格程度 |
|---|---|
| Word | 非常宽容 |
| Google Docs | 中等 |
| LibreOffice | 严格 |
| 编辑器引擎 | 非常严格 |
特定编辑器的 bug 往往源于规范的结构假设,而 Word 则悄悄忽略这些假设。
为什么我要记录这个
这个 bug 仍未解决,但调试过程揭示了一个可能的根本原因(重复的 pic:cNvPr/@id)。分享这段经历可能会帮助其他遇到类似编辑器特定渲染怪异的用户,同时也提醒大家在“在 Word 中看起来没问题”之外,对 DOCX 输出进行验证。
如果你也遇到过 DOCX 图像渲染的类似行为,我真的很想听听你的发现。