Apache Tika: Самое точное определение mime-типа файл, даже если расширение изменено.

apache tika

Столкнулся с проблемой когда необходимо было по куче файлов с расширением .bin определить тип каждого и раскидать их по реальным типам по соответствующим папкам и восстановить расширение.

В моём случае расширение bin это результат работы некого приложения, которое таким образом скрывает реальное имя файла и его расширение.

В общем была папка с файлами типа {GUID}.bin. Я знал, что это там в основном файлы с типами PDF | DOCX | XLSX и картинки.

Какими то простыми способами не удалось вычислить тип. В поисках решения я пришёл к Apache Tika.

Apache Tikaпроект\библиотека целью, которой является определение типов файлов и получение их содержимого. Наиболее часто используется в реализации поисковых систем, для индексации содержимого документов в них и последующего поиска по ним.

Maven

<dependency>
   <groupId>org.apache.tika</groupId>
   <artifactId>tika-core</artifactId>
   <version>1.27</version>
 </dependency>
 <dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.27</version>
 </dependency>

После этого самым простым способом попытался получить тип:

Java

final String type = new Tika().detect(Paths.get("/путь/к/файлу.bin").toFile());

Вроде как заработало, да вот не совсем, стали определяться картинки, PDF-ки, а вот с файлами MS Office проблема осталась, т.к. современные docx, xlsx — это zip — архивы, которые внутри содержат xml-документы и вот Tika и определяет их как application/zip или application/x-tika-ooxml. Поиск решения продолжился…

В результате решением было добавить несколько Detector-ов, которые могут просматривать контент внутри архива.

Решение

Maven

<dependency>
   <groupId>org.apache.tika</groupId>
   <artifactId>tika-core</artifactId>
   <version>1.27</version>
</dependency>
<dependency>
   <groupId>org.apache.tika</groupId>
   <artifactId>tika-parsers</artifactId>
   <version>1.27</version>
   </dependency>
 <dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi</artifactId>
   <version>5.1.0</version>
   </dependency>
 <dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi-ooxml</artifactId>
   <version>5.1.0</version>
 </dependency>

Java

public class FileUtils {

    private final static Detector detector = getDefaultDetector();


    private static Detector getDefaultDetector() {

        List<Detector> detectors = new ArrayList<>();
        detectors.add(new ZipContainerDetector());
        detectors.add(new POIFSContainerDetector());
        detectors.add(MimeTypes.getDefaultMimeTypes());

        return new CompositeDetector(detectors);
    }

   /**
     * Проверка файла на тип pdf|docx|xlsx
     *
     * @param file
     * @return
     */
    public static String getFileMime(File file) {
        try {
            final InputStream fileInputStream = new BufferedInputStream(new FileInputStream(file));
            MediaType mediaType = detector.detect(fileInputStream, new Metadata());
            if (mediaType.getSubtype().equals("pdf")) {
                return "pdf";
            } else if (mediaType.getSubtype().equals("vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
                return "xlsx";
            } else if (mediaType.getSubtype().equals("vnd.openxmlformats-officedocument.wordprocessingml.document")) {
                return "docx";
            } else {
                System.out.println("Не удалось подставить тип файла " + file + ". Тип " + mediaType.getSubtype());
                return "-";
            }

        } catch (IOException e) {
            System.out.println("Не удалось прочитать тип файла " + file);
        }
        return "-";
    }
}

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *