Получение подтипа MimeType с помощью Apache tika - PullRequest
10 голосов
/ 21 августа 2011

Мне нужно получить MediaType iana.org, а не application / zip или application / x-tika-msoffice для таких документов, как odt, ppt, pptx, xlsx и т. Д.

Если вы посмотрите на mimetypes.xml, то есть элементы mimeType, состоящие из mime-типа iana.org и "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>

Как получить имя mime-типа iana.org вместо имени родительского типа?

При тестировании обнаружения MIME-типа я делаю:

MediaType mediaType = MediaType.parse(tika.detect(inputStream));
String mimeType = mediaType.getSubtype();

Результаты теста:

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>

Есть ли способ получить фактический подтип из mimetypes.xml? Вместо x-tika-msoffice или application / zip?

Более того, я никогда не получаю application / x-tika-ooxml, а application / zip для документов xlsx, docx, pptx.

Ответы [ 4 ]

23 голосов
/ 01 июля 2012

Изначально Tika поддерживала обнаружение только по Mime Magic или по расширению файла (glob), так как это все самое большое обнаружение пантомимы до того, как это сделала Tika.

Из-за проблем с Mime Magic и globs, когда дело доходит дообнаруживая форматы контейнеров, было решено добавить несколько новых детекторов в Tika для их обработки.Контейнерные детекторы извлекали весь файл, открывали и обрабатывали контейнер, а затем определяли точный тип файла на основе содержимого.Изначально вам нужно было вызывать их явно, но затем они были заключены в 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);

Если вы запускаете это только с Core Tika jar (tika-core-1.2 -....), то присутствует только один детекторбудет волшебной пантомимой, и вы получите обнаружение старого стиля, основанное только на магии + шар.Тем не менее, если вы запустите это с помощью jika-кода Core и Parser Tika (плюс их зависимости) или из приложения Tika (которое автоматически включает core + parsers + зависимости), тогда DefaultDetector будет использовать все различные детекторы контейнеров для обработки вашего файла.,Если ваш файл основан на zip, то обнаружение будет включать обработку структуры zip для определения типа файла на основе того, что там находится.Это даст вам высокую точность обнаружения, которую вы ищете, без необходимости вызывать множество различных анализаторов по очереди.DefaultDetector будет использовать все доступные детекторы.

5 голосов
/ 26 июня 2012

Для тех, у кого есть аналогичная проблема, но с использованием более новой версии Tika, это должно сработать:

  1. Используйте ZipContainerDetector, поскольку у вас может не быть ContainerAwareDetector.* Дайте TikaInputStream методу detect() детектора, чтобы Тика могла проанализировать правильный тип пантомимы.

Мой пример кода выглядит следующим образом:

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;
}

Обратите внимание, что класс Document является частью моей модели предметной области.Так что у вас наверняка будет что-то похожее в этой строке.

Я надеюсь, что кто-то может использовать это.

2 голосов
/ 08 марта 2015

Вы можете использовать пользовательский конфигурационный файл tika:

MimeTypes mimes=MimeTypesFactory.create(Thread.currentThread()
   .getContextClassLoader().getResource("tika-custom-MimeTypes.xml"));
Metadata metadata = new Metadata();
metadata.add(Metadata.RESOURCE_NAME_KEY, file.getName());
tis = TikaInputStream.get(file);
String mimetype = new  DefaultDetector(mimes).detect(tis,metadata).toString();

В классах WEB-INF / поместите "tika-custom-MimeTypes.xml" с вашими изменениями:

В моем случае:

<mime-type type="video/mp4">
    <magic priority="60">
      <match value="ftypmp41" type="string" offset="4"/>
      <match value="ftypmp42" type="string" offset="4"/>
      <!-- add -->
      <match value="ftyp" type="string" offset="4"/>
    </magic>
    <glob pattern="*.mp4"/>
    <glob pattern="*.mp4v"/>
    <glob pattern="*.mpg4"/>
    <!-- sub-class-of type="video/quicktime" /-->
</mime-type>
<mime-type type="video/quicktime">
    <magic priority="50">
      <match value="moov" type="string" offset="4"/>
      <match value="mdat" type="string" offset="4"/>
      <!--remove for videos of screencast -->
      <!--match value="ftyp" type="string" offset="4"/-->
    </magic>
    <glob pattern="*.qt"/>
    <glob pattern="*.mov"/>
</mime-type>
2 голосов
/ 22 августа 2011

Правила обнаружения шаблонов байтов по умолчанию в tika-core могут определять только общий формат OLE2 или ZIP, используемый всеми типами документов MS Office. Вы хотите использовать 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;
}

Таким образом, ваши тесты должны пройти

...