Detekcja typu plików z Apache Tika
Zdarza się, że aplikacja nad którą pracujemy wymaga od nas wykrycia formatu pliku bazując tylko na jego zawartości. Przykładem może być mechanizm kontroli typu uploadowanych danych działający odrobinę inteligentniej niż przez analizowanie rozszerzenia. Oczywiście jest to wykonalne dla większości popularnych formatów, które posiadają pewne stałe, charakterystyczne wzorce. Żmudne jednak byłoby budowanie bazy z takimi informacjami na własną rękę, a następnie implementowanie algorytmu, który ją wykorzysta. Na szczęście jedną z największych zalet Javy jest ogromna ilość gotowych framework’ów. Również w tym przypadku się nie zawiedziemy – do swojej dyspozycji mamy bowiem Apache Tika.
Przygotowania
Narzędzie to służy do analizowania oraz parsowania zawartości plików przeróżnych formatów. My skupimy się jedynie na pierwszym zastosowaniu, jako że chodzi nam tylko o odkrycie prawdziwego typu pliku. Aby skorzystać z dobrodziejstw Apache Tika, należy dołączyć odpowiednie pliki JAR do projektu. Można to zrobić w standardowy sposób, ściągając je z tego miejsca i ręcznie przenosząc do odpowiedniego katalogu, lub ułatwić sobie sprawę korzystając z Maven’a. Wtedy konieczne jest dodanie tylko jednej zależności do pliku pom.xml.
<dependency> <groupId>org.apache.tika</groupId> <artifactId>tika-core</artifactId> <version>0.8</version> </dependency>
Jeśli zależy nam jedynie na wykrywaniu typu plików, to tika-core w zupełności wystarczy. W przypadku bardziej skomplikowanych zadań wymagających parsowania dokumentów, konieczne jest użycie innej zależności. Szczegółowe informacje na temat plików JAR składających się na Apache Tika, zależności maven’owych, i sytuacji w których są one wymagane można znaleźć na oficjalnej stronie projektu.
Zabawa w detektywów
Na potrzeby przykładu stworzyłem plik PDF o losowej treści, a następnie zmieniłem jego rozszerzenie na .jpg. Zobaczmy, czy Tika poradzi sobie z wykryciem prawdziwego formatu danych testowych.
public static void main(String... args) throws IOException {
String filename = "D:/test.jpg";
InputStream in = new BufferedInputStream(new FileInputStream(new File(filename)));
Metadata meta = new Metadata();
MimeTypes mimes = TikaConfig.getDefaultConfig().getMimeRepository();
try {
MediaType type = mimes.detect(in, meta);
System.out.println("Detected MIME: " + type.getType() + "/" + type.getSubtype());
} finally {
in.close();
}
}
Wydruk „application/pdf” mówi sam za siebie. Jest to typ MIME testowanego pliku wykryty przez używany framework. Przyjrzyjmy się teraz bliżej w jaki sposób detekcji tej dokonaliśmy. Kluczem jest klasa MimeTypes, będąca repozytorium wiedzy związanej z rozmaitymi typami danych. Dzięki temu na podstawie określonych wzorców znalezionych w naszym pliku możliwe jest zaklasyfikowanie go do jednego ze znanych formatów. Dostęp do obiektu tego typu daje nam klasa TikaConfig. W przykładzie korzystamy z domyślnej bazy dostarczanej wraz z biblioteką (plik tika-mimetypes.xml), ale mamy również możliwość stworzenia własnej, jeśli ktoś czuje się na siłach. Do uruchomienia procesu analizy danych służy metoda detect. Pochodzi ona z interfejsu Detector implementowanego przez klasę MimeTypes, który stanowi bazę dla mechanizmów rozpoznawania danych w Apache Tika. Wspomniana metoda przyjmuje dwa argumenty:
- InputStream input – dane, które chcemy przeanalizować.
- Metadata metadata – dodatkowe informacje na temat pliku, które mogą pomóc w określeniu jego typu.
Obiekt typu Metadata pozwala na przechowywanie wartości skojarzonych z pewnym kluczem. Podczas analizy danych pod kątem ich faktycznego typu, pod uwagę brane są tylko dwie informacje:
- Nazwa pliku, z którego dane pochodzą (Metadata.RESOURCE_NAME_KEY).
- Domniemany typ pliku (Metadata.CONTENT_TYPE).
W przykładzie zdecydowałem się nie podawać żadnych dodatkowych informacji, by nie zafałszowały one wyniku. Jeśli jednak ktoś chce pomóc w detekcji poprzez ujawnienie np. nazwy pliku, może to zrobić w następujący sposób:
meta.set(Metadata.RESOURCE_NAME_KEY, "test.jpg");
Analogicznie wygląda informowanie o domniemanym typie – używamy jedynie innego klucza (Metadata.CONTENT_TYPE).
Mystery solved!
Z obiektu typu MediaType, który zwraca metoda detect, jesteśmy w stanie pobrać typ i podtyp, które razem składają się na typ MIME. Na tym nasze zadanie kończy się. Ostatnią rzeczą o której należy pamiętać, jest zamknięcie strumienia do testowanego pliku. Metoda detect, jak można przeczytać w dokumentacji, nie robi tego automatycznie, zatem obowiązek ten spada na nas.

Ciekawy projekt … przez googlowanie trafilem tu i widze ze stronka dopiero wystartowala wiec powodzenia zycze … bo poki co jakosc artow daje rade
Dzięki za pochlebny komentarz!
Strona rzeczywiście jest jeszcze stosunkowo „młoda”, ale usilnie pracujemy nad tym, by ciągle wzbogacać ją nowymi i ciekawymi artykułami. Zapraszamy do częstego odwiedzania :)