首页
学习
活动
专区
圈层
工具
发布

SpringBoot + Apache tika 轻松实现各种文档内容解析

文件上传这块,很多人第一反应还是先按后缀名分支:pdf走一套,docx走一套,xlsx再抄一套。代码写到第三个格式的时候,自己都开始嫌弃。真到了线上,用户传个老版doc、ppt、odt,再来一份带附件的邮件文件,解析链路马上就乱。

这种事我一般不先写一堆if else,先找一个能把“识别格式”和“抽取内容”一把兜住的东西。Apache Tika 干的就是这个活。放进 SpringBoot 里,接口层收文件,服务层丢给 Tika,先拿正文,再按需要补元数据,基本就够用了。写法上也不重。整体思路和参考文里那种“直接落问题、少讲空话”的气质是一致的。

先把依赖加上:

  <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-web</artifactId>

  </dependency>

  <dependency>

      <groupId>org.apache.tika</groupId>

      <artifactId>tika-core</artifactId>

      <version>2.9.2</version>

  </dependency>

  <dependency>

      <groupId>org.apache.tika</groupId>

      <artifactId>tika-parsers-standard-package</artifactId>

      <version>2.9.2</version>

  </dependency>

这里我一般直接上standard-package,别一开始就省那点包体积。你要解析 Word、Excel、PDF、PPT,最后大概率还是会补回来。

核心服务不用写复杂,先把最小闭环跑通:

@Service

publicclass DocumentParseService {

  public ParsedDoc parse(MultipartFile file) {

      if (file == null || file.isEmpty()) {

          thrownew IllegalArgumentException("文件不能为空");

      }

      try (InputStream inputStream = file.getInputStream()) {

          AutoDetectParser parser = new AutoDetectParser();

          BodyContentHandler handler = new BodyContentHandler(-1);

          Metadata metadata = new Metadata();

          ParseContext context = new ParseContext();

          parser.parse(inputStream, handler, metadata, context);

          ParsedDoc result = new ParsedDoc();

          result.setFileName(file.getOriginalFilename());

          result.setContentType(metadata.get(Metadata.CONTENT_TYPE));

          result.setContent(handler.toString().trim());

          result.setTitle(metadata.get(TikaCoreProperties.TITLE));

          result.setAuthor(metadata.get(TikaCoreProperties.CREATOR));

          return result;

      } catch (Exception e) {

          thrownew RuntimeException("文档解析失败: " + file.getOriginalFilename(), e);

      }

  }

}

BodyContentHandler(-1)这个地方别偷懒。很多人默认不设,文档一大,正文直接被截断,前面看着正常,后面悄悄没了。这个坑跟线上超时、默认配置那类问题一个味道:不是不能用,是默认值未必适合你。

接口层就很薄,别把解析逻辑塞控制器里:

@RestController

@RequestMapping("/doc")

publicclass DocumentController {

  privatefinal DocumentParseService documentParseService;

  public DocumentController(DocumentParseService documentParseService) {

      this.documentParseService = documentParseService;

  }

  @PostMapping("/parse")

  public ParsedDoc parse(@RequestParam("file") MultipartFile file) {

      return documentParseService.parse(file);

  }

}

返回对象简单点,够用就行:

public class ParsedDoc {

  private String fileName;

  private String contentType;

  private String title;

  private String author;

  private String content;

  // getter/setter

}

跑起来之后,常见格式像pdf、docx、xlsx、pptx,Tika 基本都能认。它的好处不只是“能解析”,而是你不需要自己维护一堆格式判断。比如用户传了个扩展名写错的文件,单靠后缀你容易误判,Tika 会先探测 MIME 类型,再决定用哪个解析器,这一步能省掉不少脏活。

再往前走一步,实际项目里我一般会补两个东西。

第一个是大小限制,不然用户甩个 200MB 扫描版 PDF 过来,接口线程卡着不动,GC 也开始抖:

spring:

servlet:

  multipart:

    max-file-size: 20MB

    max-request-size: 20MB

第二个是异步化。解析小文件同步搞没问题,批量导入、知识库入库这种场景,最好扔线程池或者 MQ,别让上传接口一直等。尤其是 OCR、图片型 PDF,那已经不是“轻松解析”了,是另一类活。

最后说句实在的。SpringBoot + Tika 这套东西,最值钱的不是代码有多花,而是你终于不用围着文件后缀打转。上传、识别、抽取正文、拿元数据,这条链路先统一起来,后面做检索、摘要、敏感词扫描、向量化入库,路就顺了。

有些技术看上去只是省几百行代码,真到项目里,它省的是你后面一串分支判断和排障时间。这个才值钱。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/O8wEZKkryh5JP5oOrrJv7vVQ0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。
领券