记一次项目改造中使用 Apache Tika 遇到的 Bug
背景
项目中原本使用 POI 读取 Word 文件,但线上一直偶发读取异常。
后来排查发现,一个比较“奇葩”的业务习惯是:
业务老师经常把文件名在 .dox 和 .docx 之间来回修改,用来绕过系统的文件类型限制。
这种情况下,单纯依赖文件后缀判断格式就很容易出问题。
于是决定引入 Apache Tika,用内容识别方式替代原来的 POI 读取逻辑。
由于项目年代比较久,仍然运行在 JDK8 上,因此 Tika 版本只能选择 2.9.4( 官方首页 中明确说明了版本兼容关系)。
问题
在处理一些由 .dox 直接改名为 .docx 的文件时,解析结果出现大量乱码,例如:
\ndocProps/app.xml\n 10 4554 4597 35 9 3 false false 4663 WPS Office_12.1.0.22529_F1E327BC-269C-435d-A152-05C5408002CA 0\n\n\n\ndocProps/core.xml\n 2021-09-17T10:07:00Z A xxx 2025-09-02T06:45:33Z\n\n\n\ndocProps/custom.xml\n 2052-12.1.0.22529
正文内容
DF9D75DXXXXXE7BC61F2D477 eyJoZGlkIxxxxzM3NzgxxxNzc0NTcifQ==\n\n\n\nword/styles.
仔细看这些内容,其实不是乱码,而是 zip 内部结构信息。
这说明 Tika 并没有按 Word 文档解析,而是把 .docx 当成普通 zip 在读取。
问题基本可以确定为:解析器没有正确生效。
分析过程
1. 检查是否加载了正确的 Parser
首先怀疑是不是相关 jar 没加载成功。
因为 .docx 的解析依赖 tika-parser-microsoft-module,
于是直接上 Arthas 查看类加载情况:
[arthas@56]$ sc -d org.apache.tika.parser.microsoft.ooxml.OOXMLParser
关键输出如下:
code-source file:/home/admin/product-dashscope.jar!/BOOT-INF/lib/tika-parser-microsoft-module-2.9.4.jar!/
class-loader LaunchedURLClassLoader
同时确认:
sc -d org.apache.tika.Tika
输出:
code-source tika-core-2.9.4.jar
可以确认:
- OOXMLParser 已加载
- tika-core 版本正确
- classloader 正常
- 不是 jar 丢失问题
emmm,看着没问题,继续排查吧。
2. 检查 MIME 自动识别是否失败
第二个怀疑点是:
Tika 是否错误识别了文件类型。
于是植入测试代码:
new Tika().detect(file):
application/vnd.openxmlformats-officedocument.wordprocessingml.document
返回值是标准的 .docx MIME 类型。
同时打印:
new AutoDetectParser().getParsers().keySet():
[application/vnd.ms-htmlhelp, message/rfc822, application/vnd.visio, application/atom+xml, image/x-xcf, image/wmf, audio/midi, application/x-matlab-data, application/deflate64, application/vnd.apple.keynote, audio/x-flac, application/vnd.oasis.opendocument.spreadsheet-template, audio/mp4, application/x-xliff+xml, application/x-quattro-pro; version=9, application/x-ibooks+zip, application/x-plist, application/pdf, application/vnd.apple.unknown.13, application/mp4, application/x-midi, audio/x-oggpcm, application/rss+xml, text/html, text/csv, image/vnd.microsoft.icon, video/quicktime, audio/speex, video/mp4, application/zlib, application/x-wacz, application/vnd.apple.numbers, application/x-archive, application/vnd.ms-word2006ml, application/x-tika-msoffice, application/x-font-adobe-metric, video/x-m4v, application/java-archive, application/sldworks, application/x-httpresponse, application/x-tika-ooxml-protected, image/heif, application/vnd.ms-outlook, image/heic, application/x-compress, audio/x-oggflac, image/vnd.dwg, text/x-groovy, video/3gpp, application/vnd.oasis.opendocument.chart-template, application/zip, application/vnd.oasis.opendocument.text-master, audio/ogg; codecs=opus, application/vnd.oasis.opendocument.tika.flat.document, image/vnd.adobe.photoshop, image/gif, application/x-sharedlib, application/java-vm, image/webp, application/x-activemime, application/vnd.adobe.indesign-idml-package, application/vnd.wap.xhtml+xml, video/ogg, application/applefile, audio/x-aiff, application/vnd.ms-spreadsheetml, application/msword, application/vnd.apple.numbers.13, application/x-bplist-memgraph, application/x-java-pack200, application/vnd.oasis.opendocument.image-template, application/warc, application/rtf, image/bpg, application/vnd.oasis.opendocument.text, video/daala, application/x-tnef, video/x-dirac, application/x-xz, image/vnd.wap.wbmp, video/theora, application/kate, application/pkcs7-mime, audio/ogg; codecs=speex, application/x-executable, application/x-coredump, application/x-msaccess, application/vnd.apple.numbers.18, text/plain, image/png, application/vnd.ms-outlook-pst, application/x-cpio, application/x-tika-msworks-spreadsheet, application/vnd.apple.pages, audio/ogg, application/x-tar, application/vnd.oasis.opendocument.presentation-template, application/x-bplist, image/x-jbig2, application/x-dbf, video/x-ogm, application/mbox, application/vnd.oasis.opendocument.formula, application/chm, application/vnd.ms-excel.workspace.3, application/vnd.ms-excel.workspace.4, image/x-bpg, application/x-xliff+zip, application/vnd.apple.iwork, image/heic-sequence, application/vnd.ms-excel.sheet.2, application/vnd.ms-excel.sheet.3, application/x-brotli, application/dif+xml, application/vnd.ms-excel, application/vnd.ms-excel.sheet.4, application/x-tika-ole-drm-encrypted, application/vnd.ms-project, image/vnd.dgn; version=8, application/epub+zip, application/x-sas-data, application/x-snappy, application/vnd.oasis.opendocument.text-template, application/x-bplist-webarchive, application/xml, application/vnd.oasis.opendocument.flat.presentation, image/bmp, video/x-ogguvs, application/vnd.wordperfect; version=6.x, application/xhtml+xml, application/pkcs7-signature, application/vnd.wordperfect; version=5.1, application/vnd.wordperfect; version=5.0, text/x-java-source, application/vnd.sun.xml.writer, audio/basic, application/vnd.oasis.opendocument.formula-template, application/x-tmx, audio/opus, application/vnd.ms-powerpoint, application/timestamped-data, text/x-c++src, application/x-bplist-itunes, image/tiff, application/vnd.ms-wordml, application/x-object, application/x-asp, application/x-mspublisher, application/x-hwp-v5, application/x-rar-compressed, image/heif-sequence, application/vnd.oasis.opendocument.graphics-template, application/vnd.ms-tnef, application/vnd.oasis.opendocument.text-web, application/x-maker, image/emf, application/x-bzip, application/vnd.oasis.opendocument.graphics, text/vnd.iptc.anpa, application/vnd.apple.keynote.18, application/x-tika-msoffice-embedded; format=ole10_native, application/x-arj, application/x-lzma, video/3gpp2, video/x-oggrgb, audio/mpeg, application/vnd.apple.keynote.13, application/x-lz4, application/vnd.oasis.opendocument.flat.spreadsheet, audio/vnd.wave, application/vnd.oasis.opendocument.presentation, application/vnd.mif, application/x-7z-compressed, image/jxl, video/x-oggyuv, application/x-msdownload, application/vnd.oasis.opendocument.chart, image/jpeg, image/icns, audio/vorbis, application/ogg, image/svg+xml, application/warc+gz, application/onenote; format=one, video/x-flv, application/x-ms-owner, application/gzip, application/x-tika-unix-dump, application/vnd.oasis.opendocument.spreadsheet, application/vnd.apple.pages.18, application/vnd.oasis.opendocument.image, application/x-bzip2, application/vnd.apple.pages.13, application/x-fictionbook+xml, application/vnd.oasis.opendocument.flat.text, application/x-elf, text/tsv, application/x-chm, application/x-font-ttf, application/x-prt]
也能看到 application/vnd.openxmlformats-officedocument.wordprocessingml.document 对应解析器。
说明:
文件类型识别正常。
这个又被排除了......
3. 怀疑 Jar 兼容性
前面两条线都没问题,问题就开始变得有点诡异了。
这时候开始怀疑:
会不会是依赖冲突导致解析器虽然加载了,但实际不可用?
于是执行:
jar tf product-dashscope.jar | grep [tika 关键组件名]
把 Tika 相关的依赖全部列出来,再结合 tika 的 pom,
逐个比对实际运行时依赖版本。
这里偷了个懒,把依赖列表直接丢给 AI 做了一轮兼容性分析。
结果还真命中:
项目中显式引入的 POI 版本过低,与 Tika 自带版本不兼容。
当 OOXMLParser 解析失败时,
Tika 会 fallback 到 ZipParser,
于是就出现了前面看到的 zip 结构内容。
最终解决
回头检查项目 pom,发现确实手动引入了旧版本 POI:
<dependency>
<groupId>org.apache.poi</groupId>
...
</dependency>
处理方式也很简单:
删除显式 POI 依赖,完全使用 Tika 自带版本。
重新打包发布后:
- 乱码问题消失
- Word 内容解析恢复正常
- 回归测试全部通过
问题彻底解决。
总结
这次问题本质上不是 Tika 的 Bug,而是一个比较典型的 依赖冲突导致功能降级 的案例,有几点经验值得记下来:
1. 出现“解析结果像另一种格式”时,要考虑 fallback
这次看到 zip 结构时,其实已经给了一个很明显的信号:
解析失败了,但系统没有报错,而是退回到了备用解析器。
很多框架(包括 Tika)都有 fallback 机制,
结果不对不一定是失败,也可能是降级执行。
这一点非常关键。
2. Parser 加载成功 ≠ 一定能正常工作
Arthas 能看到类加载成功,只能说明:
类存在。
但不能保证:
依赖版本一定兼容。
如果底层依赖不匹配,Parser 依然可能在运行时 silently fail。
3. 使用“集成型框架”时,尽量不要手动覆盖核心依赖
像 Tika 这种工具,本身会带一整套经过验证的依赖组合。
如果项目中再显式引入:
- POI
- PDFBox
- Commons 等核心组件
就很容易产生 版本错位问题。
经验建议:
优先使用框架自带依赖,除非明确知道自己在做什么。
4. 当问题变得诡异时,依赖冲突往往是高概率原因
这类问题的典型特征是:
- 本地正常
- 线上异常
- 没有明显报错
- 行为看起来“不合理”
如果同时满足这些条件,第一时间就应该检查依赖树。
很多时候,比业务逻辑更容易出问题、更难排查的,其实是依赖管理。