# TikaTest **Repository Path**: null_412_9848/TikaTest ## Basic Information - **Project Name**: TikaTest - **Description**: test apache tika - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 3 - **Forks**: 0 - **Created**: 2020-06-11 - **Last Updated**: 2026-03-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 测试 Tika Apache Tika用于文件类型检测和从各种格式的文件中提取文本内容。 Tika的使用方式很简单: ``` public void testTikaParseEmlWithDocAttachment() throws TikaException, SAXException, IOException { String filename="eml-with-doc-attachment-test.eml"; AutoDetectParser autoParser = new AutoDetectParser(); ContentHandler contentHandler = new ToXMLContentHandler(); Metadata metadata = new Metadata(); InputStream stream =this.getClass().getClassLoader().getResourceAsStream(Paths.get(inputDir,filename).toString()); autoParser.parse(stream, contentHandler, metadata); } ``` 其中,autoParser可以自动输入的检测文档的类型,调用合适的解析器去解析文档,将结果写入到Metadata和ContentHandler中,Metadata保存的是输入文档的元信息, 比如文档的创建人创建时间等等。文档的内容的内容保存在ContentHandler的Writer中。如果想要将文档输出为xhtml格式,可以选用ToXMLContentHandler类型的参数, 如果只想要输出文档的内容,可以用BodyContentHandler类型的参数。 # Eml 对于eml文件,直接用ToXMLContentHandler或者BodyContentHandler可以将eml文件提取为xhtml或者纯文本的格式。但是有一个问题就是邮件的正文和附件都会拼接到一起, 合成为一个文件,如果是想要将每个文件的内容单独提取出来,就需要换一种方式来提取了: ``` public List extract(InputStream inputStream) throws TikaException, SAXException, IOException { Parser p = new AutoDetectParser(); ContentHandlerFactory factory = new BasicContentHandlerFactory( BasicContentHandlerFactory.HANDLER_TYPE.HTML, -1); RecursiveParserWrapper wrapper = new RecursiveParserWrapper(p); Metadata metadata = new Metadata(); //metadata.set(RESOURCE_NAME_KEY, "test_recursive_embedded.docx"); ParseContext context = new ParseContext(); RecursiveParserWrapperHandler handler = new RecursiveParserWrapperHandler(factory, -1); wrapper.parse(inputStream, handler, metadata, context); return handler.getMetadataList(); } ``` 这种方式,提取的结果会被存入到一个Metadata中的List中,list中的每个元素都是HashMap,一个HashMap对应邮件的正文或者邮件的附件或者是附件 中嵌入的文件,比如word中的图片,或者是压缩包中的文件。而HashMap的内容则包含对应文件的内容和元信息。 其中X-TIKA:embedded_depth的值表示的是对应文件嵌套深度,X-TIKA:embedded_resource_path表示的是从当前文件是嵌在哪个文件中的。 而如果想提取eml文件的附件: ``` public class EmbeddedFilesExtractor { private Parser parser = new AutoDetectParser(); private Detector detector = ((AutoDetectParser) parser).getDetector(); private TikaConfig config = TikaConfig.getDefaultConfig(); String RESOURCE_NAME_KEY = "resourceName"; public void extract(InputStream is, Path outputDir) throws SAXException, TikaException, IOException { Metadata m = new Metadata(); ParseContext c = new ParseContext(); ContentHandler h = new BodyContentHandler(-1); c.set(Parser.class, parser); EmbeddedDocumentExtractor ex = new MyEmbeddedDocumentExtractor(outputDir, c); c.set(EmbeddedDocumentExtractor.class, ex); parser.parse(is, h, m, c); } private class MyEmbeddedDocumentExtractor extends ParsingEmbeddedDocumentExtractor { private final Path outputDir; private int fileCount = 0; private MyEmbeddedDocumentExtractor(Path outputDir, ParseContext context) { super(context); this.outputDir = outputDir; } @Override public boolean shouldParseEmbedded(Metadata metadata) { return true; } @Override public void parseEmbedded(InputStream stream, ContentHandler handler, Metadata metadata, boolean outputHtml) throws SAXException, IOException { //try to get the name of the embedded file from the metadata String name = metadata.get(RESOURCE_NAME_KEY); if (name == null) { name = "file_" + fileCount++; } else { //make sure to select only the file name (not any directory paths //that might be included in the name) and make sure //to normalize the name name = name.replaceAll("\u0000", " "); int prefix = FilenameUtils.getPrefixLength(name); if (prefix > -1) { name = name.substring(prefix); } name = FilenameUtils.normalize(FilenameUtils.getName(name)); } //now try to figure out the right extension for the embedded file MediaType contentType = detector.detect(stream, metadata); if (name.indexOf('.') == -1 && contentType != null) { try { name += config.getMimeRepository().forName( contentType.toString()).getExtension(); } catch (MimeTypeException e) { e.printStackTrace(); } } Path outputFile = outputDir.resolve(name); if (Files.exists(outputFile)) { outputFile = outputDir.resolve(UUID.randomUUID().toString()+"-"+name); } Files.createDirectories(outputFile.getParent()); Files.copy(stream, outputFile); } } } ``` 这种方式也可以提取压缩包内的文件或者是word中的图片。但是不会再递归的提取下去,只提取当前输入文件所直接包含的文件。 ### 可提取的元信息 邮件主题 创建人 创建时间 发件人 收件人 MIME-version 无附件的元信息 ## 输出形式 可以输出为xhtml文件,纯文本文件,可提取邮件附件文件,可分别提取邮件的正文和附件 ## Word ### 可提取的元信息 标题 作者 最后一次保存者 创建时间 最后一次修改时间 最后一次打印时间 文档字数 文档类型 页数 模板 ## 输出形式 可以输出为xhtml文件,和纯文本文件,可以保留word中的表格结构。 可以提取页眉页脚批注,但是失去了位置信息 word中的图片,在输出为xhtml文件的时候,命名规则是从imagen加图像扩展名的格式 # Excel ###可提取的元信息 标题 作者 最后一次保存者 创建时间 最后一次修改时间 最后一次打印时间 文档类型 ## 输出形式 可以输出为xhtml文件,和纯文本文件,可以保留Excel中的表格结构。 # PPT ### 可提取的元信息 标题 作者 最后一次保存者 创建时间 最后一次修改时间 最后一次打印时间 文档字数 文档类型 页数 模板 ## 输出形式 可以输出为xhtml文件,可以保留PPT中的表格结构。 # PDF ### 可提取的元信息 标题 作者 创建时间 最后一次修改时间 文档类型 页数 创建工具 ## 输出形式 可以输出为xhtml文件,可以保留word中的表格结构。 # 压缩包 支持的压缩包格式: Tar, AR, ARJ, CPIO, Dump, Zip, 7Zip, Gzip, BZip2, XZ, LZMA, Z and Pack200. # 遗留问题 提取eml-with-doc-attachment-test.eml中的word附件文件名乱码导致是输出失败问题。 提取eml-with-table.eml文件时文件内容乱码问题 # 国内的git仓库地址 方便下载 git@gitee.com:null_412_9848/TikaTest.git