Получение типа MIME файла в Java

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

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

18 ответов


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


к сожалению,

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

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

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

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

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

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

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


API JAF является частью 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);

С 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 богаты, он может анализировать "что угодно". По состоянию на TIKA-core 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 для получения дополнительной информации.


Apache Tika предложения тика-ядро обнаружение типа mime на основе магических маркеров в префиксе потока. tika-core не извлекает другие зависимости, что делает его таким же легким, как текущий unmaintained Утилита Обнаружения Типа 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.обнаруживать.(..) не может использоваться напрямую (тика-1120). Больше намеков на https://tika.apache.org/0.10/detection.html.


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

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

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

С roseindia:

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");

Если вы застряли с java 5-6 тогда этот класс утилиты от servoy open source product

https://github.com/Servoy/servoy-client/blob/e7f5bce3c3dc0f0eb1cd240fce48c75143a25432/servoy_shared/src/com/servoy/j2db/util/MimeTypes.java#L34

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

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

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


мне просто интересно, как большинство людей получают тип 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();
}

я попробовал несколько способов сделать это, включая первые, сказанные @Joshua Fox. Но некоторые не распознают частые типы mimetypes, как для PDF-файлов, а другие не могут быть надежными с поддельными файлами (я пытался с файлом RAR с расширением, измененным на TIF). Решение, которое я нашел, как также сказал @Joshua Fox поверхностным образом, заключается в использовании MimeUtil2, например:

MimeUtil2 mimeUtil = new MimeUtil2();
mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

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

сначала вы можете проверить тип mimeType и проверить его.

во-вторых, вы должны преобразовать первые 4 байта вашего файла в шестнадцатеричные, а затем сравнить его с магическими числами. Тогда это будет действительно безопасный способ проверить валидацию файлов.


скинуться с моими 5 центов:

TL, DR

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

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

прежде всего, список типов 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.типы в папке META-INF в вашем проекте
  2. добавьте строку для каждого типа mime, который вам нужен, и реализация по умолчанию не предоставляет (есть сотни типов mime, и список растет со временем).

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

image/png png PNG
application/javascript js

мима.типы формат файла, смотрите более подробную информацию здесь: https://docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.html

определить тип файла из содержимого файла

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

чтобы получить тип mime для файла, вы просто используете файлы и этого в код:

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

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

еще раз, ваниль реализация этого (тот, который поставляется с JDK) оставляет много, чтобы быть желанный.

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

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


Это самый простой способ я нашел для этого:

byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);

Если вы работаете на ОС Linux ,есть командная строка file --mimetype:

String mimetype(file){

   //1. run cmd
   Object cmd=Runtime.getRuntime().exec("file --mime-type "+file);

   //2 get output of cmd , then 
    //3. parse mimetype
    if(output){return output.split(":")[1].trim(); }
    return "";
}

затем

mimetype("/home/nyapp.war") //  'application/zip'

mimetype("/var/www/ggg/au.mp3") //  'audio/mp3'

весной MultipartFile;

org.springframework.сеть.составной.MultipartFile

file.getContentType();


попробовав различные другие библиотеки, я остановился на mime-util.

<groupId>eu.medsea.mimeutil</groupId>
      <artifactId>mime-util</artifactId>
      <version>2.1.3</version>
</dependency>

File file = new File("D:/test.tif");
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(file);
System.out.println(mimeTypes);

public String getFileContentType(String fileName) {
    String fileType = "Undetermined";
    final File file = new File(fileName);
    try
    {
        fileType = Files.probeContentType(file.toPath());
    }
    catch (IOException ioException)
    {
        System.out.println(
                "ERROR: Unable to determine file type for " + fileName
                        + " due to exception " + ioException);
    }
    return fileType;
}

вы можете сделать это только с одной строкой:MimetypesFileTypeMap().getContentType (новый файл ("filename.ext")). Смотреть полный тестовый код (Java 7):

import java.io.File;
import javax.activation.MimetypesFileTypeMap;
public class MimeTest {
    public static void main(String a[]){
         System.out.println(new MimetypesFileTypeMap().getContentType(
           new File("/path/filename.txt")));
    }
}

этот код выдает следующий вывод:text / plain