PAYATHON 2026

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() 的内部调用逐项计时,定位实际瓶颈。

备注:内容仅供参考。