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