1. Обзор
В этом уроке мы рассмотрим различные стратегии получения MIME-типов файла. Мы рассмотрим способы расширения типов MIME, доступных для стратегий, где это применимо.
Мы также укажем, где мы должны предпочесть одну стратегию другой.
2. Использование Java 7
Начнем с Java 7, которая предоставляет метод Files.probeContentType(path)
для разрешения типа MIME:
@Test
public void whenUsingJava7_thenSuccess() {
Path path = new File("product.png").toPath();
String mimeType = Files.probeContentType(path);
assertEquals(mimeType, "image/png");
}
Этот метод использует установленные реализации FileTypeDetector
для проверки типа MIME. Он вызывает probeContentType
каждой реализации для разрешения типа.
Теперь, если файл распознается любой из реализаций, возвращается тип содержимого. Однако, если этого не происходит, вызывается системный детектор типов файлов по умолчанию.
Однако реализации по умолчанию зависят от ОС и могут дать сбой в зависимости от используемой ОС.
В дополнение к этому также важно отметить, что стратегия потерпит неудачу, если файл отсутствует в файловой системе. Кроме того, если файл не имеет расширения, это приведет к ошибке.
3. Использование URLConnection
URLConnection
предоставляет несколько API для определения типов файлов MIME. Кратко рассмотрим каждый из них.
3.1. Использование getContentType()
Мы можем использовать метод getContentType()
URLConnection
для получения MIME-типа файла:
@Test
public void whenUsingGetContentType_thenSuccess(){
File file = new File("product.png");
URLConnection connection = file.toURL().openConnection();
String mimeType = connection.getContentType();
assertEquals(mimeType, "image/png");
}
Однако основным недостатком этого подхода является то, что он очень медленный .
3.2. Использование предположенияContentTypeFromName()
Далее, давайте посмотрим, как мы можем использовать методgueContentTypeFromName()
для этой цели:
@Test
public void whenUsingGuessContentTypeFromName_thenSuccess(){
File file = new File("product.png");
String mimeType = URLConnection.guessContentTypeFromName(file.getName());
assertEquals(mimeType, "image/png");
}
Этот метод использует внутреннюю FileNameMap
для разрешения типа MIME из расширения .
У нас также есть возможность использовать вместо этого методgueContentTypeFromStream()
, который использует первые несколько символов входного потока для определения типа.
3.3. Использование getFileNameMap
()
Более быстрый способ получить тип MIME с помощью URLConnection
— использовать метод getFileNameMap()
:
@Test
public void whenUsingGetFileNameMap_thenSuccess(){
File file = new File("product.png");
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor(file.getName());
assertEquals(mimeType, "image/png");
}
Метод возвращает таблицу типов MIME, используемых всеми экземплярами URLConnection.
Затем эта таблица используется для определения типа входного файла.
Встроенная таблица типов MIME очень ограничена, когда речь идет о URLConnection
.
По умолчанию класс использует `` файл content-types.properties в JRE_HOME
/lib
. Однако мы можем расширить его, указав пользовательскую таблицу с помощью свойства content.types.user.table :
System.setProperty("content.types.user.table","<path-to-file>");
4. Использование MimeTypesFileTypeMap
MimeTypesFileTypeMap
разрешает типы MIME, используя расширение файла. Этот класс появился в Java 6 и, следовательно, очень удобен, когда мы работаем с JDK 1.6.
Теперь давайте посмотрим, как его использовать:
@Test
public void whenUsingMimeTypesFileTypeMap_thenSuccess() {
File file = new File("product.png");
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file.getName());
assertEquals(mimeType, "image/png");
}
Здесь мы можем либо передать имя файла, либо сам экземпляр файла
в качестве параметра функции. Однако функция с экземпляром File
в качестве параметра внутренне вызывает перегруженный метод, который принимает имя файла в качестве параметра.
Внутри этот метод ищет разрешение типа в файле с именем mime.types
. Очень важно отметить, что метод ищет файл в определенном порядке:
- Программно добавленные записи в экземпляр
MimetypesFileTypeMap
- .
mime.types
в домашнем каталоге пользователя <java.home>/lib/mime.types
- ресурсы с именем
META-INF/mime.types
- ресурс с именем
META-INF/mimetypes.default
(обычно находится только в файлеактивации.jar )
Однако, если файл не найден, он вернет application/octet-stream
в качестве ответа.
5. Использование jMimeMagic
jMimeMagic — это библиотека с ограниченной лицензией, которую мы можем использовать для получения MIME-типа файла.
Начнем с настройки зависимости Maven:
<dependency>
<groupId>net.sf.jmimemagic</groupId>
<artifactId>jmimemagic</artifactId>
<version>0.1.5</version>
</dependency>
Мы можем найти последнюю версию этой библиотеки на Maven Central .
Далее мы рассмотрим, как работать с библиотекой:
@Test
public void whenUsingJmimeMagic_thenSuccess() {
File file = new File("product.png");
Magic magic = new Magic();
MagicMatch match = magic.getMagicMatch(file, false);
assertEquals(match.getMimeType(), "image/png");
}
Эта библиотека может работать с потоком данных и, следовательно, не требует присутствия файла в файловой системе.
6. Использование Apache Tika
Apache Tika — это набор инструментов, который обнаруживает и извлекает метаданные и текст из различных файлов. Он имеет богатый и мощный API и поставляется с tika-core , который мы можем использовать для определения MIME-типа файла.
Начнем с настройки зависимости Maven:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.18</version>
</dependency>
Далее мы воспользуемся методом detect() для определения типа:
@Test
public void whenUsingTika_thenSuccess() {
File file = new File("product.png");
Tika tika = new Tika();
String mimeType = tika.detect(file);
assertEquals(mimeType, "image/png");
}
Библиотека использует магические маркеры в префиксе потока для разрешения типов.
7. Заключение
В этой статье мы рассмотрели различные стратегии получения MIME-типа файла. Кроме того, мы также проанализировали компромиссы подходов. Мы также указали сценарии, в которых мы должны отдавать предпочтение одной стратегии перед другой.
Полный исходный код, который используется в этой статье , как всегда доступен на GitHub .