Получение Mime-типа файла в Java - PullRequest
323 голосов
/ 09 сентября 2008

Мне было просто интересно, как большинство людей выбирают mime-тип из файла на Java? До сих пор я пробовал два утилиты: JMimeMagic & Mime-Util.

Первый дал мне исключения памяти, второй не закрывает свои потоки должным образом. Мне просто интересно, есть ли у кого-нибудь еще метод / библиотека, которые они использовали и работали правильно?

Ответы [ 19 ]

311 голосов
/ 23 января 2012

В Java 7 теперь вы можете просто использовать Files.probeContentType(path).

204 голосов
/ 11 мая 2009

К сожалению,

mimeType = file.toURL().openConnection().getContentType();

не работает, так как при использовании URL-адреса файл блокируется, поэтому, например, его невозможно восстановить.

Однако у вас есть это:

mimeType= URLConnection.guessContentTypeFromName(file.getName());

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

InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream

Однако, как следует из приведенного выше комментария, встроенная таблица типов MIME довольно ограничена, не включая, например, MSWord и PDF. Итак, если вы хотите обобщить, вам нужно выйти за пределы встроенных библиотек, используя, например, Mime-Util (отличную библиотеку, использующую как расширение файла, так и содержимое).

50 голосов
/ 14 декабря 2009

JAF API является частью JDK 6. Посмотрите на пакет javax.activation.

Наиболее интересными классами являются javax.activation.MimeType - фактический держатель типа MIME - и javax.activation.MimetypesFileTypeMap - класс, экземпляр которого может разрешать тип MIME в виде строки для файла:

String fileName = "/path/to/file";
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

// only by file name
String mimeType = mimeTypesMap.getContentType(fileName);

// or by actual File instance
File file = new File(fileName);
mimeType = mimeTypesMap.getContentType(file);
38 голосов
/ 14 февраля 2017

С Apache Tika вам нужно только три строки кода :

File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));

Если у вас отличная консоль, просто вставьте и запустите этот код, чтобы поиграть с ним:

@Grab('org.apache.tika:tika-core:1.14')
import org.apache.tika.Tika;

def tika = new Tika()
def file = new File("/path/to/file")
println tika.detect(file)

Имейте в виду, что его API богаты, он может анализировать "что угодно". Начиная с версии 1.14, у вас есть:

String  detect(byte[] prefix)
String  detect(byte[] prefix, String name)
String  detect(File file)
String  detect(InputStream stream)
String  detect(InputStream stream, Metadata metadata)
String  detect(InputStream stream, String name)
String  detect(Path path)
String  detect(String name)
String  detect(URL url)

См. apidocs для получения дополнительной информации.

27 голосов
/ 18 мая 2013

Apache Tika предлагает в tika-core определение типа пантомимы, основанное на магических маркерах в префиксе потока. tika-core не извлекает другие зависимости, что делает его таким же легковесным, как и не поддерживаемая в настоящее время Утилита обнаружения типа Mime .

Простой пример кода (Java 7) с использованием переменных theInputStream и theFileName

try (InputStream is = theInputStream;
        BufferedInputStream bis = new BufferedInputStream(is);) {
    AutoDetectParser parser = new AutoDetectParser();
    Detector detector = parser.getDetector();
    Metadata md = new Metadata();
    md.add(Metadata.RESOURCE_NAME_KEY, theFileName);
    MediaType mediaType = detector.detect(bis, md);
    return mediaType.toString();
}

Обратите внимание, что MediaType.detect (...) нельзя использовать напрямую ( TIKA-1120 ). Больше подсказок предоставляется на https://tika.apache.org/0.10/detection.html.

21 голосов
/ 15 декабря 2012

Если вы разработчик Android, вы можете использовать служебный класс android.webkit.MimeTypeMap, который сопоставляет MIME-типы с расширениями файлов и наоборот.

Следующий фрагмент кода может вам помочь.

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
17 голосов
/ 01 августа 2011

С розеиндия :

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");
14 голосов
/ 05 сентября 2013

Если вы застряли с Java 5-6 , то этот служебный класс из servoy open source product .

Вам нужна только эта функция

public static String getContentType(byte[] data, String name)

Он проверяет первые байты содержимого и возвращает типы содержимого на основе этого содержимого, а не по расширению файла.

13 голосов
/ 25 июня 2013

Мне было просто интересно, как большинство людей выбирают mime-тип из файла на Java?

Я опубликовал мой SimpleMagic Java-пакет, который позволяет определять тип контента (mime-тип) из файлов и байтовых массивов. Он предназначен для чтения и запуска магических файлов команд Unix file (1), которые являются частью большинства ~ конфигураций ОС Unix.

Я попробовал Apache Tika, но он огромный с тоннами зависимостей, URLConnection не использует байты файлов, а MimetypesFileTypeMap также просто смотрит на имена файлов.

С SimpleMagic вы можете сделать что-то вроде:

// create a magic utility using the internal magic file
ContentInfoUtil util = new ContentInfoUtil();
// if you want to use a different config file(s), you can load them by hand:
// ContentInfoUtil util = new ContentInfoUtil("/etc/magic");
...
ContentInfo info = util.findMatch("/tmp/upload.tmp");
// or
ContentInfo info = util.findMatch(inputStream);
// or
ContentInfo info = util.findMatch(contentByteArray);

// null if no match
if (info != null) {
   String mimeType = info.getMimeType();
}
5 голосов
/ 25 сентября 2017

Чтобы скинуть мои 5 центов:

TL, DR

Я использую MimetypesFileTypeMap и добавляю в файл mime.types любой mime, которого там нет, и он мне особенно нужен.

А теперь длинное чтение:

Прежде всего, список типов MIME огромный , см. Здесь: https://www.iana.org/assignments/media-types/media-types.xhtml

Мне нравится сначала использовать стандартные средства, предоставляемые JDK, и если это не сработает, я пойду и поищу что-нибудь еще.

Определить тип файла по расширению файла

Начиная с 1.6, Java имеет MimetypesFileTypeMap, как указано в одном из ответов выше, и это самый простой способ определить тип mime:

new MimetypesFileTypeMap().getContentType( fileName );

В его ванильной реализации это мало что делает (то есть работает для .html, но не для .png). Однако очень просто добавить любой тип контента, который вам может понадобиться:

  1. Создайте файл с именем «mime.types» в папке META-INF в вашем проекте
  2. Добавьте строку для каждого типа MIME, который вам нужен, и реализация по умолчанию не предоставляет (существуют сотни типов MIME, и список увеличивается с течением времени).

Пример записи для файлов png и js:

image/png png PNG
application/javascript js

Подробнее о формате файла mime.types см. Здесь: https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html

Определение типа файла по содержимому файла

Начиная с версии 1.7, Java имеет java.nio.file.spi.FileTypeDetector , который определяет стандартный API для определения типа файла в специфичном для реализации пути .

Чтобы получить MIME-тип для файла, вы просто должны использовать Files и сделать это в своем коде:

Files.probeContentType(Paths.get("either file name or full path goes here"));

Определение API предоставляет средства, которые поддерживают либо определение типа MIME файла по имени файла, либо по содержимому файла (магические байты). Вот почему метод probeContentType () выдает IOException, если реализация этого API использует предоставленный ему Path, чтобы фактически попытаться открыть связанный с ним файл.

Опять же, ванильная реализация этого (того, что поставляется с JDK) оставляет желать лучшего.

В каком-то идеальном мире в далекой-далекой галактике все эти библиотеки, которые пытаются решить эту проблему типа файла-пантомимы, просто реализуют java.nio.file.spi.FileTypeDetector , вы бы поместили jar-файл предпочтительной библиотеки реализации в ваш путь к классам, и это было бы так.

В реальном мире, где вам нужен раздел TL, DR, вы должны найти библиотеку с большинством звездочек рядом с ее названием и использовать ее. Для этого конкретного случая он мне не нужен (пока;)).

...