用Apache Tika解析文档
作者:程序员马丁
热门项目实战社群,收获国内众多知名公司面试青睐,近千名同学面试成功!助力你在校招或社招上拿个offer。
读文件没那么简单
假设你正在做一个毕业设计:构建一个基于大模型的智能问答系统,用户可以上传公司内部文档,然后针对这些文档进行提问。
听起来很清晰,技术路线大概是:
用户上传文档 → 解析文档内 容 → 存入向量数据库 → 用户提问 → 检索相关内容 → 喂给大模型 → 返回答案
你可能觉得"解析文档内容"这一步很简单——不就是读文件吗?
// 你以为的代码
String content = Files.readString(Path.of("report.pdf"));
然后你会发现:这行代码根本跑不通。
1. 你以为的文档解析 vs 真实世界的文档
1.1 PDF:同一个后缀,完全不同的内心
你收到三份 PDF 文件:
| 文件 | 来源 | 你尝试复制粘贴 | 结果 |
|---|---|---|---|
report1.pdf | Word 导出的 | 能复制 | 正常 |
report2.pdf | 扫描仪扫的 | 选不中任何文字 | 空白 |
report3.pdf | 某老系统生成 | 复制出来全是乱码 | ¿½Ð |
同样是 .pdf 后缀,内部结构可能完全不同:
- 文字型 PDF:内部存储的是文字编码,可以直接提取。
- 扫描型 PDF:内部存储的是图片,文字只是“画”上去的。
- 混合型 PDF:部分页是文字,部分页是扫描图。
你写的 readString() 根本不知道怎么处理这些差异。
1.2 Word 文档:远比你想象的复杂
一份 .docx 文件,打开看起来就是几段文字。但你用代码读出来可能是这样:
公司简介
成立时间 2015年
员工人数 500人
第 1 页,共 3 页
本文档为内部资料,请勿外传
问题在哪?
- 表格被拆成了莫名其妙的换行。
- 页眉页脚混进了正文。
- 多余的空行和空格。
- 文档属性(作者、创建时间)你根本没拿到。
1.3 文件后缀:会骗人的
File file = new File("data.txt");
// 你以为是文本文件,其实...
真实场景:
- 有人把
.xlsx改成了.txt(怕被邮件系统拦截)。 - 有人把
.exe改成了.docx(别问为什么)。 - 有人上传的
.pdf其实是 HTML 改的后缀。
只看后缀判断文件类型 = 100% 会翻车。
1.4 编码问题:中文乱码重灾区
鎮ㄥソ锛屾杩庝娇鐢? // 这是什么鬼?
原因:文件是 GBK 编码,你用 UTF-8 读取。
或者反过来:文件是 UTF-8,你用 GBK 读取。
更惨的情况:一份文档里混合了多种编码(别笑,真的有)。
2. 当你要构建 RAG 知识库时,这些问题会全部爆发
2.1 为什么文档解析是第一道坎?
RAG 的核心思路是:
不要让大模型凭空回答,而是先从你的文档库里检索相关内容,把检索结果喂给大模型,让它基于这些内容来回答。
2.2 如果文档解析这一步出了问题
| 问题 | 后果 |
|---|---|
| 扫描 PDF 解析为空 | 这份文档的知识完全丢失 |
| 表格变成乱换行 | 检索时匹配不到,或者匹配到无意义片段 |
| 元数据丢失 | 用户问“这是哪个部门的文件”,你答不上来 |
| 乱码 | 向量化结果是垃圾,检索结果也是垃圾 |
| 页眉页脚混入 | 每个切片都带着“第X页/共Y页”,浪费 token |
结论:文档解析的质量,直接决定了你整个 RAG 系统的上限。
3. 专业的文档解析工具
到这里,你应该理解了:解析文档不是一个 readFile() 能搞定的事。
你需要一个工具:
- 能自动识别文件的真实类型(不靠后缀)
- 能处理几十种文档格式(PDF、Word、PPT、Excel、HTML、邮件...)
- 能提取文本内容。
- 能提取元数据(作者、创建时间、标题...)
- 能处理编码问题。
- 能对接 OCR(处理扫描件)
- 最好是开源免费的。
这个工具就是 Apache Tika。
GitHub 地址:https://github.com/apache/tika
认识 Apache Tika
1. Tika 解决什么问题
Apache Tika 是 Apache 基金会的开源项目,专门用于内容检测和内容提取。
用一句话概括:
给 Tika 一个文件(不管什么格式),它还你干净的文本和元数据。

2. Tika 支持的文件格式
Tika 支持 1000+ 种 MIME 类型,常见的包括:
| 类别 | 格式 |
|---|---|
| 文档 | PDF, DOC, DOCX, ODT, RTF, TXT |
| 表格 | XLS, XLSX, CSV, ODS |
| 演示 | PPT, PPTX, ODP |
| 图片 | JPG, PNG, GIF, TIFF, BMP |
| 网页 | HTML, XML, XHTML |
| 压缩 | ZIP, TAR, GZIP, 7Z |
| 邮件 | EML, MSG, MBOX |
| 电子书 | EPUB, MOBI |
| 音视频 | MP3, MP4, AVI(提取元数据) |
3. 两种使用方式
| 方式 | 说明 | 适用场景 |
|---|---|---|
| 作为 Java 依赖库 | 直接在项目中引入 tika-core 和 tika-parsers,代码里调用 | 单体应用、解析量不大、对延迟敏感 |
| 作为独立服务(Tika Server) | 用 Docker 跑一个 Tika 服务,通过 HTTP 接口调用 | 微服务 架构、多语言、需要隔离、解析量大 |
咱们下文主要以 Java 依赖库 的方式来讲解;至于 独立服务部署 这种形态,大家了解即可。当然,我也会顺带说明两者的区别,以及各自更适合的使用场景。
核心概念详解
1. MIME 类型:文件的身份证
1.1 什么是 MIME 类型
MIME(Multipurpose Internet Mail Extensions)类型是互联网标准,用于标识文件的真实格式。
格式是 类型/子类型,比如:
| MIME 类型 | 对应格式 |
|---|---|
text/plain | 纯文本 |
text/html | HTML |
application/pdf | |
application/vnd.openxmlformats-officedocument.wordprocessingml.document | DOCX |
image/png | PNG 图片 |
application/zip | ZIP 压缩包 |
1.2 为什么不能只看文件后缀
// 危险的做法
if (filename.endsWith(".pdf")) {
// 当作 PDF 处理
}
问题 1:后缀可以随便改
mv malware.exe report.pdf # 后缀是 pdf,内容是 exe
问题 2:后缀可能丢失
# 有些系统传文件会丢后缀
upload_12345678 # 这是什么文件?
问题 3:后缀和内容不匹配
用户把 Excel 文件后缀改成 .txt 发邮件(绕过附件限制),你的系统收到后按 .txt 处理,直接炸了。
1.3 Tika 如何检测真实 MIME 类型
Tika 使用魔数检测(Magic Number Detection):
PDF 文件的前几个字节是:%PDF-
ZIP 文件的前几个字节是:PK
PNG 图片的前几个字节是:‰PNG
Tika 读取文件的头部字节,与已知的签名库比对,从而判断真实类型。
// Tika 检测 MIME 类型
Tika tika = new Tika();
String mimeType = tika.detect(new File("unknown_file"));
// 返回 application/pdf,不管文件后缀是什么
2. 文本抽取:拿到可用的文字内容
2.1 什么是文本抽取
从各种格式的文件中,提取出纯文本内容。
输入:一份带格式的 Word 文档(有字体、颜色、表格、图片)
输出:纯文字字符串(没有格式信息)
2.2 为什么不能直接读字节
byte[] bytes = Files.readAllBytes(Path.of("report.docx"));
String content = new String(bytes, StandardCharsets.UTF_8);
// 结果:一堆乱码 + 不可见字符
因为 .docx 本质是一个 ZIP 压缩包,里面是一堆 XML 文件。你直接读字节,读到的是 ZIP 的二进制结构。
2.3 文本抽取在 RAG 中的价值
| 用途 | 说明 |
|---|---|
| 向量化 | 只有文本才能被 Embedding 模型处理 |
| 全文检索 | ElasticSearch 等搜索引擎索引的是文本 |
| 切片 | 按句子/段落切分,需要先有文本 |
| 展示 | 给用户看原文片段 |