快速结论:当 CONTENT_EXTRACTION_ENGINE 设为 docling 或 tika 时,以 application/octet-stream 上传的 .md / .markdown / .txt / .rst 文件会被送进 Docling/Tika 重新解析,而不是用 TextLoader 原样读取,导致 Markdown 结构(尤其是表格和行内代码)被破坏。优先排查客户端的 multipart content type 及引擎分支中的 _is_text_file 扩展名白名单。
适用环境:Open WebUI v0.11.4;dev 分支(24c01bd)代码路径未变但未实际运行;安装方式为 Docker;macOS 15(Colima),Kubernetes 上也有出现;内容提取引擎为 docling-serve 1.34.0 或 Tika。Issue 未提供 Python、CUDA、显卡等信息。
最快修复方案:暂无确认的一步修复方案。Issue 中给出的方向是把 md、markdown、txt、rst 加入 _is_text_file 的扩展名检查(与 slim 路径使用同一份列表),可优先尝试;客户端侧修复见 open-webui/oikb#128(Issue 未说明其状态)。
注意事项:上述代码改动只是 Issue 作者提出的思路,Issue 关闭时未确认是否已合并;在上游修复前,规避手段是让客户端以 text/markdown 上传,而不是 application/octet-stream。若 Markdown 已被 Docling/Tika 重新渲染并入库,已存储的 file.data.content 是引擎输出而非原文,需要重新上传才能恢复。
问题场景
在 Open WebUI 中把内容提取引擎配置为 Docling 或 Tika,然后上传 Markdown 文件。当上传请求的 multipart 类型是 application/octet-stream 时,文件不会走文本加载路径,而是被送到 Docling/Tika 做转换,最终存进 file.data.content 的是引擎重新渲染后的文本。Python 3.11 的 mimetypes 没有 .md 条目,slim 镜像也不带 /etc/mime.types,因此官方 oikb 镜像上传的每个 .md 都会以 octet-stream 发送,触发该问题。在知识库预览和引用中表现为 Markdown 格式、表格内容丢失或错位。
报错原文
issue: .md uploaded as application/octet-stream is sent to the extraction engine (Docling/Tika) instead of TextLoader
_is_text_file only checks the content type and known_source_ext, and `md` is not in that list.
The default and slim paths already treat `md`/`markdown`/`txt` as text by extension (loaders/main.py:705); the engine branches (:561, :614) do not.
POST /v1/convert/file
原因分析
最可能的原因是引擎分支中的文件类型判断只看 multipart content type 和 known_source_ext 列表,而 md 不在该列表中。默认路径和 slim 路径已按扩展名把 md / markdown / txt 当作纯文本处理(loaders/main.py:705),但 Docling 分支(:561)和 Tika 分支(:614)没有同样的扩展名判断。因此当客户端把 .md 标为 application/octet-stream 时,文件被误判为需要提取引擎处理的二进制文档。复现实验显示,Docling 会重新渲染 Markdown,含行内代码或单元格内 <br> 的表格会被拆散、行丢失(docling-project/docling#3991)。
环境排查
- 确认 Open WebUI 版本(Issue 中为 v0.11.4;
dev分支 24c01bd 代码路径未变)。 - 确认安装方式(Issue 中为 Docker;Kubernetes 上也出现)。
- 确认
CONTENT_EXTRACTION_ENGINE的取值(docling或tika)。 - 确认内容提取引擎版本(Issue 中为 docling-serve 1.34.0)。
- 检查客户端上传
.md时实际发送的 multipart content type 是application/octet-stream还是text/markdown。 - 确认运行环境是否缺少
/etc/mime.types,以及 Python 版本(Issue 提到 Python 3.11 的mimetypes无.md条目)。 - 操作系统:macOS 15(Colima),以及 Kubernetes 环境。
解决步骤
- 先确认触发条件:把 Content Extraction Engine 设为 Docling(docling-serve 1.34.0)。
- 构造一个含表格的 Markdown 文件,内容如:
| Endpoint | p50 |/| --- | --- |/| `/v1/schema` | 34 |/| `/v2/invoice` | 59 |。 - 用
curl -F "file=@doc.md;type=application/octet-stream" .../api/v1/files/上传,模拟客户端以 octet-stream 发送。 - 调用
GET /api/v1/files/{id}/data/content,观察返回内容:若表格变成空行表头、行内代码被拆成散落文本、每个数字单独成表,说明复现成功。 - 作为临时规避,把同一个文件以
text/markdown上传再对比,Issue 中该方式下内容与源文件逐字节一致。 - 代码层面的可优先尝试修改:在
_is_text_file的扩展名检查中加入md、markdown、txt、rst,与 slim 路径保持一致,使引擎分支也按扩展名把 Markdown 交给TextLoader。 - 若需要客户端侧处理,可查看 open-webui/oikb#128 的修复状态。
验证方法
用 GET /api/v1/files/{id}/data/content 读取已上传文件的内容,与源 Markdown 文件逐字节或逐行比对:若内容与原文一致、表格行和行内代码保持完整,则问题已解决。另可对照 docling-serve 日志:如果 octet-stream 上传不再出现 POST /v1/convert/file,说明文件已走 TextLoader。Issue 中的对照数据是 7 个测试文件(5 KB 到 620 KB),octet-stream 下出现 145 个表格单元格重排、2 个单元格丢失,而 text/markdown 下 0 差异。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。


