Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

К сожалению,

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 (отличная библиотека, использующая как расширение файла, так и содержимое).

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);

С Апач Тика тебе нужно только три строки кода:

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)

Видеть апидоки Чтобы получить больше информации.

Апач Тика предложения в тика-ядро обнаружение типа mime на основе магических маркеров в префиксе потока. 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(...) нельзя использовать напрямую (ТИКА-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);
}

От Розиндия:

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

Если вы застряли на Java 5-6 тогда этот служебный класс из продукт с открытым исходным кодом Servoy.

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

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();
}

Внесу свои 5 копеек:

ТЛ,ДР

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

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

Прежде всего, список типов 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.probeContentType(Paths.get("either file name or full path goes here"));

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

И снова ваниль выполнение этот (тот, который поставляется с JDK) оставляет желать лучшего.

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

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

Я попробовал несколько способов сделать это, включая первый, предложенный @Joshua Fox.Но некоторые не распознают частые типы mime-типов, например файлы 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 байта вашего файла в шестнадцатеричный формат, а затем сравнить их с магическими числами.Тогда это будет действительно безопасный способ проверки файлов.

весной Мультичастный файл файл;

org.springframework.web.multipart.MultipartFile

file.getContentType();

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

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'

Попробовав различные другие библиотеки, я остановился на 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")));
    }
}

Этот код выдает следующий результат: текстовый/обычный

File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top