OpenTBS 加载 DOCX 时 MsWord_Clean() 很慢,能否关闭清理?
结论
MsWord_Clean() 用于清理可能干扰模板字段识别的 Word XML 标记。固定模板需要反复使用时,建议先生成优化模板,供后续请求使用。设置 $TBS->OtbsClearMsWord = false 可以跳过清理,但应先验证字段合并和文档布局。
关闭清理后文档看起来正常,只能说明当前模板和已测试的数据没有暴露相关问题,不能据此判断以后编辑过的模板也不需要清理。
为什么 Word 模板需要清理
Word 中看起来连续的文字,在 DOCX 内部可能分散在多个 XML 文本节点中。拼写检查和编辑记录等信息也可能插入其中,导致屏幕上完整的 TBS 字段在底层被拆开。
下面是一个简化示意,字段名称仅用于说明:
<w:r><w:t>[customer.</w:t></w:r>
<w:r><w:t>name]</w:t></w:r>
Word 可以将它显示为 [customer.name],但模板引擎处理的是 XML 字符串,中间的标记可能影响字段识别。
在所核对的 OpenTBS 源码中,MsWord_Clean() 会移除部分校对、语言及分页缓存标记,清理 _GoBack 系统书签和部分编辑记录属性,再尝试合并重复的文本运行结构。具体处理范围应以实际安装版本为准。OpenTBS 源码
预先优化与关闭清理有什么区别
OPENTBS_MAKE_OPTIMIZED_TEMPLATE 会将预处理后的模板保存为新文件,供后续重复加载。官方文档将它用于缓解模板子文件清理或准备过程导致的加载缓慢。模板优化说明
两种方式的区别在于:
- 预先优化模板:先完成预处理,后续复用处理结果。首次生成优化文件仍需承担处理成本。
- 关闭清理:直接跳过
MsWord_Clean(),模板中可能干扰合并的结构会保留下来。
OpenTBS 的更新记录还说明,已经处理过的模板可以避免重复优化。因此,预先生成优化文件适合反复使用的固定模板。OpenTBS 更新记录
如何使用优化模板
以下代码假定 $TBS 已初始化并安装 OpenTBS 插件。
在模板发布或更新时执行一次:
$template = '/path/to/template.docx';
$new_template = '/path/to/template.optimized.docx';
$TBS->OtbsClearMsWord = true;
$TBS->Plugin(OPENTBS_MAKE_OPTIMIZED_TEMPLATE, $template, $new_template);
后续生成文档时,加载保存的优化文件:
$TBS->LoadTemplate('/path/to/template.optimized.docx');
// 在这里执行现有的字段和区块合并逻辑。
不要在每次请求中重新生成优化文件,否则仍会反复产生预处理成本。原模板修改后,应重新生成并验证优化文件。
什么情况下可以关闭清理
如果模板来源可控,且所有相关字段都已验证能够正确合并,可以考虑在加载前关闭清理:
$TBS->OtbsClearMsWord = false;
$TBS->LoadTemplate('/path/to/template.docx');
验证时应检查实际合并结果,覆盖普通字段、重复区块,以及模板中使用的页眉、页脚和表格内容。除了排版,还要确认没有残留占位符、遗漏替换或异常的区块重复。
模板在 Word 中再次编辑、保存后,内部 XML 可能发生变化,需要重新验证。这个开关只控制对应的 Word 清理步骤,并不表示关闭所有 DOCX 预处理。
为什么 1.6 MB 的文件也会处理很久
DOCX 是压缩包,文件大小和页数不足以反映内部 XML 的处理量。大量碎片化的文本节点和编辑标记可能增加扫描、查找和字符串替换的成本。
根据题述,耗时已定位到 MsWord_Clean()。但缺少具体模板、安装版本和各子步骤的耗时,无法确定是哪类结构导致处理超过 80 秒。可以先比较原模板和优化模板的加载耗时,并检查合并结果。如果优化后仍然缓慢,再对 MsWord_Clean() 的内部调用逐项计时,定位实际瓶颈。
备注:内容仅供参考。
