使用Apache tika获取MimeType子类型

lis*_*sak 10 java detection mime-types apache-tika

对于像odt,ppt,pptx,xlsx等文档,我需要获取iana.org MediaType而不是application/zip或application/x-tika-msoffice.

如果你看一下mimetypes.xml,那么mimeType元素由iana.org mime-type和"sub-class-of"组成.

   <mime-type type="application/msword">
    <alias type="application/vnd.ms-word"/>
    ............................
    <glob pattern="*.doc"/>
    <glob pattern="*.dot"/>
    <sub-class-of type="application/x-tika-msoffice"/>
  </mime-type>
Run Code Online (Sandbox Code Playgroud)

如何获取iana.org mime-type名称而不是父类型名称?

在测试mime类型检测时,我做:

MediaType mediaType = MediaType.parse(tika.detect(inputStream));
String mimeType = mediaType.getSubtype();
Run Code Online (Sandbox Code Playgroud)

检测结果 :

FAILED: getsCorrectContentType("application/vnd.ms-excel", docs/xls/en.xls)
java.lang.AssertionError: expected:<application/vnd.ms-excel> but was:<x-tika-msoffice>

FAILED: getsCorrectContentType("vnd.openxmlformats-officedocument.spreadsheetml.sheet", docs/xlsx/en.xlsx)
java.lang.AssertionError: expected:<vnd.openxmlformats-officedocument.spreadsheetml.sheet> but was:<zip>

FAILED: getsCorrectContentType("application/msword", doc/en.doc)
java.lang.AssertionError: expected:<application/msword> but was:<x-tika-msoffice>

FAILED: getsCorrectContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document", docs/docx/en.docx)
java.lang.AssertionError: expected:<application/vnd.openxmlformats-officedocument.wordprocessingml.document> but was:<zip>

FAILED: getsCorrectContentType("vnd.ms-powerpoint", docs/ppt/en.ppt)
java.lang.AssertionError: expected:<vnd.ms-powerpoint> but was:<x-tika-msoffice>
Run Code Online (Sandbox Code Playgroud)

有没有办法从mimetypes.xml获取实际的子类型?而不是x-tika-msoffice或application/zip?

此外,我从来没有获得application/x-tika-ooxml,但xlsx,docx,pptx文件的应用程序/ zip.

Gag*_*arr 23

最初,Tika只支持Mime Magic或文件扩展名(glob)的检测,因为这是Tika之前的大多数mime检测.

由于在检测容器格式时Mime Magic和globs存在问题,因此决定在Tika中添加一些新的探测器来处理这些问题.Container Aware Detectors获取整个文件,打开并处理容器,然后根据内容计算出确切的文件类型.最初,你需要明确地调用它们,但随后它们被包裹起来ContainerAwareDetector,你会在一些答案中看到它们.

从那以后,Tika添加了一个服务加载器模式,最初用于Parsers.这允许类在存在时自动加载,通常用于识别哪些类是合适的并使用它们.然后,这种支持也被扩展到覆盖探测器,此时ContainerAwareDetector可以移除旧的,以支持更清洁的东西.

如果您使用的是Tika 1.2或更高版本,并且您希望准确检测所有格式(包括容器格式),则需要执行以下操作:

 TikaConfig config = TikaConfig.getDefaultConfig();
 Detector detector = config.getDetector();

 TikaInputStream stream = TikaInputStream.get(fileOrStream);

 Metadata metadata = new Metadata();
 metadata.add(Metadata.RESOURCE_NAME_KEY, filenameWithExtension);
 MediaType mediaType = detector.detect(stream, metadata);
Run Code Online (Sandbox Code Playgroud)

如果你只使用Core Tika jar(tika-core-1.2 -....)运行它,那么唯一的探测器将是mime magics one,你将获得基于magic + glob的旧式探测器.但是,如果您使用Core和Parser Tika jar(以及它们的依赖项)或者Tika App(其中包括核心+解析器+依赖项)自动运行它,那么DefaultDetector将使用所有各种不同的容器检测器来处理您的文件.如果您的文件是基于zip的,那么检测将包括处理zip结构以根据其中的内容识别文件类型.这将为您提供高精度检测,而无需依次调用大量不同的解析器.DefaultDetector将使用所有可用的探测器.


Seb*_*ötz 5

对于其他有类似问题但使用较新的Tika版本的人来说,这应该可以解决问题:

  1. 使用,ZipContainerDetector因为你可能已经没有ContainerAwareDetector了.
  2. 给出检测器TikaInputStreamdetect()方法,以确保tika可以分析正确的哑剧类型.

我的示例代码如下所示:

public static String getMimeType(final Document p_document)
{
    try
    {
        Metadata metadata = new Metadata();
        metadata.add(Metadata.RESOURCE_NAME_KEY, p_document.getDocName());

        Detector detector = getDefaultDectector();

        LogMF.debug(log, "Trying to detect mime type with detector {0}.", detector);
        TikaInputStream inputStream = TikaInputStream.get(p_document.getData(), metadata);

        return detector.detect(inputStream, metadata).toString();
    }
    catch (Throwable t)
    {
        log.error("Error while determining mime-type of " + p_document);
    }

    return null;
}

private static Detector getDefaultDectector()
{
    if (detector == null)
    {
        List<Detector> detectors = new ArrayList<>();

        // zip compressed container types
        detectors.add(new ZipContainerDetector());
        // Microsoft stuff
        detectors.add(new POIFSContainerDetector());
        // mime magic detection as fallback
        detectors.add(MimeTypes.getDefaultMimeTypes());

        detector = new CompositeDetector(detectors);
    }

    return detector;
}
Run Code Online (Sandbox Code Playgroud)

请注意,Document该类是我的域模型的一部分.所以你肯定会在那条线上有类似的东西.

我希望有人可以使用它.


lis*_*sak 3

tika-core 中的默认字节模式检测规则只能检测所有 MS Office 文档类型使用的通用 OLE2 或 ZIP 格式。您想使用 ContainerAwareDetector 进行此类检测。并使用 MimeTypes 检测器作为其后备检测器。尝试这个 :

public MediaType getContentType(InputStream is, String fileName) {
    MediaType mediaType;
    Metadata md = new Metadata();
    md.set(Metadata.RESOURCE_NAME_KEY, fileName);
    Detector detector = new ContainerAwareDetector(tikaConfig.getMimeRepository());

    try {
        mediaType = detector.detect(is, md);
    } catch (IOException ioe) {
        whatever;
    }
    return mediaType;
}
Run Code Online (Sandbox Code Playgroud)

这样你的测试应该通过

  • ContainerAwareDetector 在 Tika 中已经被弃用了一段时间,对于今天看到这个的人来说,你应该使用 [Tika 的新 DefaultDetector](http://tika.apache.org/1.6/detection.html#The_default_Tika_Detector) 加上类路径上的所有 tika 解析器 (5认同)