如何使用Java从文件中获得媒体类型(MIME类型)?到目前为止,我已经尝试了JMimeMagic和Mime-Util。第一个给了我内存异常,第二个没有正确地关闭它的流。

您将如何探测该文件以确定其实际类型(而不仅仅是基于扩展名)?


当前回答

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

其他回答

用我的5分钱凑钱:

TL,博士

我使用MimetypesFileTypeMap,并添加任何mime,不存在,我特别需要它,到mime。类型文件。

现在,长长的一段是:

首先,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 .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附带的实现)还有很多需要改进的地方。

在遥远的银河系中的某个理想世界中,所有试图解决文件到mime类型问题的库都将简单地实现java.nio.file.spi。filettypedetector,您可以将首选实现库的jar文件放到类路径中,这就是它了。

在现实世界中,当你需要TL和DR部分时,你应该找到在它的名字旁边有最多星星的库并使用它。对于这个特定的情况,我不需要(还;))。

实际上,Apache Tika检测器Tika.detect(File)是最好的选择,比Files.probeContentType(path)更准确。

检查这个伟大的快速参考包含示例和代码示例。

如果你是一个Android开发人员,你可以使用一个工具类Android .webkit. mimetypemap,它将mime类型映射到文件扩展名,反之亦然。下面的代码片段可能对您有所帮助。 getMimeType(String fileUrl) { 字符串扩展= MimeTypeMap.getFileExtensionFromUrl(fileUrl); 返回MimeTypeMap.getSingleton () .getMimeTypeFromExtension(扩展); }

我只是想知道大多数人如何从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();
}

我找不到任何东西来检查视频/mp4 MIME类型,所以我做了自己的解决方案。 我偶然发现维基百科是错误的,并且00 00 00 18 66 74 79 70 69 73 6F 6D文件签名是不正确的。第四个字节(18)和所有70个字节(不包括)在其他有效的mp4文件中进行了相当多的更改后。

这段代码本质上是URLConnection的复制/粘贴。guessContentTypeFromStream代码,但为视频/mp4量身定制。

BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(content));
String mimeType = URLConnection.guessContentTypeFromStream(bis);

// Goes full barbaric and processes the bytes manually
if (mimeType == null){
    // These ints converted in hex ar:
    // 00 00 00 18 66 74 79 70 69 73 6F 6D
    // which are the file signature (magic bytes) for .mp4 files
    // from https://www.wikiwand.com/en/List_of_file_signatures
    // just ctrl+f "mp4"
    int[] mp4_sig = {0, 0, 0, 24, 102, 116, 121, 112};

    bis.reset();
    bis.mark(16);
    int[] firstBytes = new int[8];
    for (int i = 0; i < 8; i++) {
        firstBytes[i] = bis.read();
    }
    // This byte doesn't matter for the file signature and changes
    mp4_sig[3] = content[3];

    bis.reset();
    if (Arrays.equals(firstBytes, mp4_sig)){
        mimeType = "video/mp4";
    }
}

成功测试了10个不同的.mp4文件。

编辑:这是一个有用的链接(如果它仍然在线),在那里你可以找到许多类型的样本。我没有这些视频,也不知道谁有,但它们对测试上面的代码很有用。