Столкнулся с проблемой когда необходимо было по куче файлов с расширением .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 "-";
}
}