## 问题描述 知识库中上传 `.doc`(Word 97-2003 二进制格式)文档后,点击「预览」必然失败,弹窗显示「无法加载预览」,只有「重试 / 下载」两个按钮。 ## 复现步骤 1. 进入「知识库」,任意知识库上传一个 `.doc` 文件(Word 97-2003,非 `.docx`) 2. 等待解析状态变为 ready 3. 鼠标悬停该文档卡片,点「预览」 ## 实际行为 弹窗显示「无法加载预览」。Console 报错: ``` [DocumentPreviewCore] preview failed [object Object] TypeError: Cannot read properties of undefined (reading 'body') ``` Network 面板可见请求链: - `GET /api/knowledge-bases/{kb}/documents/{doc}/file?disposition=inline` → 200 - `GET /assets/docx-preview.*.js` → 200 即后端已正常返回文件,失败发生在前端富预览渲染阶段。 ## 期望行为 `.doc` 应降级为「抽取文本预览」,与现有 `.ppt` 的处理保持一致。 ## 根因 前端把 `.doc` 与 `.docx` 当作同一族格式,但两者的容器结构完全不同: | 格式 | 容器 | 魔数 | |---|---|---| | `.docx` | OOXML(ZIP) | `50 4b 03 04` | | `.doc` | OLE 复合文档 | `d0 cf 11 e0` | `docx-preview@^0.3.2` 是纯 OOXML 渲染器,只解析 ZIP 内的 `word/document.xml`,遇到 `.doc` 无法解析(JSZip 解包直接抛 `BadZipFile`)。 具体涉及三处: 1. `dashboard/src/utils/knowledgeDocPreview.ts` 的 `RICH_PREVIEW_EXTS` 含 `doc` → `canRichPreviewKnowledgeDocument()` 返回 `true`,放行到富预览 2. `dashboard/src/utils/docKind.ts:10`:`WORD_EXT = new Set(["docx", "doc"])` → `getDocKind()` 把 `.doc` 映射为 `"word"` 3. `dashboard/src/components/DocumentPreviewCore.tsx` 的 word 分支 → `await import("docx-preview")` → `renderAsync()` 解析失败 ## 上游已有先例 `knowledgeDocPreview.ts` 的 `TEXT_PREVIEW_EXTS` 里已把 `ppt` 降级,注释写着: > Legacy PowerPoint: no in-browser slide renderer — use extracted text. 同一份单测 `knowledgeDocPreview.test.ts` 也断言 `a.ppt → false`,但紧邻的 `a.doc → true` 却没有对应降级 —— 说明这是遗漏,不是有意设计。 ## 建议修复 ```diff const RICH_PREVIEW_EXTS = new Set([ "pdf", - "doc", "docx", "pptx", "xls", "xlsx", "xlsm", ]); ``` ```diff "tsv", // Legacy PowerPoint: no in-browser slide renderer — use extracted text. "ppt", + // Legacy Word (OLE compound document): docx-preview only parses OOXML. + "doc", ]); ``` 同时把 `knowledgeDocPreview.test.ts` 中 `a.doc` 的断言改为 `false`。 注意:`.xls` **不应**一并降级 —— SheetJS 原生支持 BIFF 格式,`.xls` 富预览是正常的。 ## 已在实际部署上验证 在 v1.0.2b9 的构建产物上按上述方案打补丁(`RICH_PREVIEW_EXTS` 移除 `doc`、`TEXT_PREVIEW_EXTS` 追加 `doc`)后实测: - `.doc`《内部审计管理制度》→ 弹窗正常渲染后端抽取文本,Console 零报错 - `.docx`《专项工程竣(交)工验收管理细则》→ 仍走 docx-preview,2 页 / 4 张表格 / 8,745 字符,版式完整 - `.xls` → 仍走 SheetJS 富预览,未受影响 - `.ppt` → 维持原有抽取文本行为 ## 环境 - Octop 版本:v1.0.2b9 - 部署方式:Docker(`ghcr.nju.edu.cn/tencentcloud/octop:latest`) - 浏览器:Chrome - 影响范围:所有上传 `.doc` 的用户,与该文件内容无关,100% 复现
Activity