在Java中获取文件的Mime类型

Lee*_*ald 329 java mime

我只是想知道大多数人如何从Java中的文件中获取mime类型?到目前为止,我已经尝试了两个工具:JMimeMagic&Mime-Util.

第一个给了我内存异常,第二个没有正确关闭它的流.我只是想知道是否有其他人有他们使用和正常工作的方法/库?

Chr*_*rth 319

在Java 7中,您现在可以使用Files.probeContentType(path).

  • 请注意,Files.probeContentType(Path)在多个操作系统上都存在错误,并且已经提交了大量错误报告.我在使用ubuntu但在Windows上失败的软件时遇到了问题.似乎在Windows上Files.probeContentType(Path)总是返回null.这不是我的系统所以我没有检查JRE或Windows版本.它可能是用于Java 7的oracle JRE的Windows 7或8. (58认同)
  • 这方面的一个主要限制是该文件必须存在于文件系统上.这不适用于流或字节数组等. (30认同)
  • 我在OS X 10.9上运行,并且我为`.xml`,`.png`和`.xhtml`文件获取`null`.我不知道我是在做一些可怕的错误,但这看起来相当可怕. (13认同)
  • 如果文件的扩展名丢失或错误,这将无用. (9认同)
  • 当我从名称中删除扩展名时,此方法无法返回mime类型.例如,如果名称为test.mp4,我将其更改为"test",方法返回null.同时我将电影扩展名更改为png等,它返回png mime类型 (3认同)

Jos*_*Fox 208

不幸,

mimeType = file.toURL().openConnection().getContentType();
Run Code Online (Sandbox Code Playgroud)

不起作用,因为这种URL的使用会使文件被锁定,因此,例如,它是不可删除的.

但是,你有这个:

mimeType= URLConnection.guessContentTypeFromName(file.getName());
Run Code Online (Sandbox Code Playgroud)

以及以下内容,其优点是不仅仅使用文件扩展名,还可以查看内容

InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream
Run Code Online (Sandbox Code Playgroud)

但是,正如上面的评论所暗示的那样,内置的mime类型表非常有限,不包括例如MSWord和PDF.所以,如果你想要概括,你需要超越内置库,使用例如Mime-Util(这是一个很棒的库,同时使用文件扩展名和内容).

  • 完美的解决方案 - 帮助了我很多!将`FileInputStream`包装到`BufferedInputStream`中是至关重要的部分 - 否则`guessContentTypeFromStream`返回`null`(传递`InputStream`实例应该支持标记) (8认同)
  • Howerver,`URLConnection`有一组非常有限的内容类型,它确实可以识别.例如,它无法检测到`application/pdf`. (8认同)
  • 它只会让它锁定,因为你没有办法将它关闭.断开URLConnection将解锁它. (3认同)
  • `guessContentTypeFromName()`使用默认的`$ JAVA_HOME/lib/content-types.properties`文件.您可以通过更改系统属性`System.setProperty("content.types.user.table","/ lib/path/to/your/property/file")来添加自己的扩展文件;` (3认同)

Ada*_*šek 50

JAF API是JDK 6的一部分.查看javax.activation包.

最有趣的类是javax.activation.MimeType- 一个实际的MIME类型持有者 - 和javax.activation.MimetypesFileTypeMap- 类,其实例可以将MIME类型解析为文件的String:

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);
Run Code Online (Sandbox Code Playgroud)

  • 你可以通过`MimetypesFileTypeMap.getDefaultFileTypeMap()跳过创建一个新对象.getContentType(file)` (6认同)
  • 不幸的是,由于`getContentType(File)`的javadoc表示:_返回文件对象的MIME类型.此类中的实现调用`getContentType(f.getName())`._ (3认同)
  • 请记住,您可以使用META-INF/mime.types文件扩展此功能,因此如果您被迫使用Java 6,它是完美的.http://docs.oracle.com/javaee/5/api/javax/activation/MimetypesFileTypeMap html的 (3认同)

lif*_*foo 43

使用Apache Tika,您只需要三行代码:

File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));
Run Code Online (Sandbox Code Playgroud)

如果你有一个groovy控制台,只需粘贴并运行此代码即可:

@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)
Run Code Online (Sandbox Code Playgroud)

请记住,它的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)
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请参阅apidocs.

  • Tika 的一件坏事是,大量的依赖膨胀。它使我的 jar 大小增加了 54MB! (2认同)
  • @helmyTika 1.17 是独立的,只有 648 KB 大。 (2认同)

kop*_*por 27

Apache Tikatika-core中提供基于流前缀中的魔术标记的mime类型检测.tika-core不会获取其他依赖项,这使得它与当前未维护的Mime类型检测实用程序一样轻量级.

简单的代码示例(Java 7),使用变量theInputStreamtheFileName

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();
}
Run Code Online (Sandbox Code Playgroud)

请注意,MediaType.detect(...)不能直接使用(TIKA-1120).https://tika.apache.org/0.10/detection.html提供了更多提示.


Paw*_*wan 23

如果您是Android开发人员,则可以使用android.webkit.MimeTypeMap将MIME类型映射到文件扩展名的实用程序类,反之亦然.

以下代码段可能会对您有所帮助.

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果尝试使用本地文件路径(例如"/sdcard/path/to/video.extension"),这也有效.问题是如果本地文件的路径中包含空格,它总是返回null (3认同)

Ali*_*aka 17

来自roseindia:

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");
Run Code Online (Sandbox Code Playgroud)

  • 无论谁投票给答案,请添加评论,以便我(和其他人)可以学习发布更好的答案. (7认同)
  • 功能很不完整.从Java 7开始,html,pdf和jpeg扩展返回正确的mime类型,但js和css返回null! (5认同)
  • 我没有投票给你,但getFileNameMap不适用于许多基本文件类型,例如'bmp'.URLConnection.guessContentTypeFromName也返回相同的内容 (3认同)

Ovi*_*gan 15

如果您遇到java 5-6那么这个实用程序类来自servoy开源产品.

你只需要这个功能

public static String getContentType(byte[] data, String name)
Run Code Online (Sandbox Code Playgroud)

它探测内容的第一个字节,并根据该内容而不是文件扩展名返回内容类型.


Gra*_*ray 13

我只是想知道大多数人如何从Java中的文件中获取mime类型?

我发布了我的SimpleMagic Java包,它允许从文件和字节数组中确定内容类型(mime类型).它旨在读取和运行Unix文件(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();
}
Run Code Online (Sandbox Code Playgroud)

  • 在多个图像文件上对其进行了测试。所有扩展名都已重命名。你很棒的图书馆处理得很好。当然它也很亮:)。 (2认同)
  • 这是一个很好的解决方案!谢谢! (2认同)

nid*_*res 5

用我的5美分筹码:

TL,DR

我使用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 );
Run Code Online (Sandbox Code Playgroud)

在它的vanilla实现中,这没有太大作用(即它适用于.html但不适用于.png).但是,添加您可能需要的任何内容类型非常简单:

  1. 在项目的META-INF文件夹中创建名为"mime.types"的文件
  2. 为你需要的每个mime类型添加一行,默认实现不提供(有数百种mime类型,列表随着时间的推移而增长).

png和js文件的示例条目是:

image/png png PNG
application/javascript js
Run Code Online (Sandbox Code Playgroud)

有关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"));
Run Code Online (Sandbox Code Playgroud)

API定义提供了支持从文件名或文件内容(魔术字节)确定文件mime类型的工具.这就是为什么probeContentType()方法抛出IOException,以防此API的实现使用提供给它的Path来实际尝试打开与之关联的文件.

同样,vanilla的实现(JDK附带的实现)还有很多不足之处.

在遥远的银河系中的一些理想世界中,所有这些试图解决这个文件到mime类型问题的库只会实现java.nio.file.spi.FileTypeDetector,你会放入首选的实现库的jar将文件存入您的类路径,就可以了.

在现实世界中,你需要TL,DR部分,你应该找到其名称旁边有大多数星星的图书馆并使用它.对于这种特殊情况,我不需要一个(还有)).