1. 概述
在本教程中,我们将了解获取文件 MIME 类型的各种策略。在适用的情况下,我们将研究扩展可用于策略的 MIME 类型的方法。
我们还将指出我们应该在哪些方面偏爱一种策略而不是另一种。
2. 使用 Java 7
让我们从 Java 7 开始——它提供了方法 Files.probeContentType(path) 来解析 MIME 类型:
@Test
public void whenUsingJava7_thenSuccess() {
Path path = new File("product.png").toPath();
String mimeType = Files.probeContentType(path);
assertEquals(mimeType, "image/png");
}
此方法使用已安装的FileTypeDetector实现来探测 MIME 类型。它调用每个实现的 probeContentType来解析类型。
现在,如果文件被任何实现识别,则返回内容类型。但是,如果没有发生这种情况,则会调用系统默认文件类型检测器。
但是,默认实现是特定于操作系统的,可能会失败,具体取决于我们使用的操作系统。
除此之外,还需要注意的是,如果文件系统中不存在该文件,则该策略将失败。此外,如果文件没有扩展名,则会导致失败。
3. 使用URLConnection
URLConnection提供了多个 API 来检测文件的 MIME 类型。让我们简要地探讨它们中的每一个。
3.1. 使用getContentType()
我们可以使用URLConnection 的getContentType()方法来检索文件的 MIME 类型:
@Test
public void whenUsingGetContentType_thenSuccess(){
File file = new File("product.png");
URLConnection connection = file.toURL().openConnection();
String mimeType = connection.getContentType();
assertEquals(mimeType, "image/png");
}
但是,这种方法的一个主要缺点是速度非常慢。
3.2. 使用guessContentTypeFromName()
接下来,让我们看看如何使用guessContentTypeFromName()来达到目的:
@Test
public void whenUsingGuessContentTypeFromName_thenSuccess(){
File file = new File("product.png");
String mimeType = URLConnection.guessContentTypeFromName(file.getName());
assertEquals(mimeType, "image/png");
}
该方法利用内部的FileNameMap以解决从扩展MIME类型。
我们还可以选择使用guessContentTypeFromStream()代替,它使用输入流的前几个字符来确定类型。
3.3. 使用getFileNameMap ()
使用URLConnection获取 MIME 类型的更快方法是使用getFileNameMap()方法:
@Test
public void whenUsingGetFileNameMap_thenSuccess(){
File file = new File("product.png");
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor(file.getName());
assertEquals(mimeType, "image/png");
}
该方法返回URLConnection的所有实例使用的 MIME 类型表。然后使用该表来解析输入文件类型。
当涉及到URLConnection时,内置的 MIME 类型表非常有限。
默认情况下,该类使用content-types.properties文件中JRE_HOME / lib目录。但是,我们可以通过使用content.types.user.table 属性指定特定于用户的表来扩展它 :
System.setProperty("content.types.user.table","<path-to-file>");
4. 使用MimeTypesFileTypeMap
MimeTypesFileTypeMap使用文件的扩展名解析 MIME 类型。这个类是 Java 6 附带的,因此当我们使用 JDK 1.6 时非常方便。
现在让我们看看如何使用它:
@Test
public void whenUsingMimeTypesFileTypeMap_thenSuccess() {
File file = new File("product.png");
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file.getName());
assertEquals(mimeType, "image/png");
}
在这里,我们可以将文件名或File实例本身作为参数传递给函数。但是,以File实例为参数的函数在内部调用了接受文件名作为参数的重载方法。
在内部,此方法查找名为mime.types 的文件以进行类型解析。需要注意的是,该方法按特定顺序搜索文件:
- 以编程方式向MimetypesFileTypeMap实例添加条目
- . 用户主目录中的mime.types
- <java.home>/lib/mime.types
- 名为META-INF/mime.types 的资源
- 名为META-INF/mimetypes.default 的资源(通常只能在activation.jar文件中找到)
但是,如果没有找到文件,它将返回application/octet-stream作为响应。
5. 使用jMimeMagic
jMimeMagic是一个限制性许可的库,我们可以使用它来获取文件的 MIME 类型。
让我们从配置 Maven 依赖项开始:
<dependency>
<groupId>net.sf.jmimemagic</groupId>
<artifactId>jmimemagic</artifactId>
<version>0.1.5</version>
</dependency>
我们可以在Maven Central上找到这个库的最新版本。
接下来,我们将探索如何使用该库:
@Test
public void whenUsingJmimeMagic_thenSuccess() {
File file = new File("product.png");
Magic magic = new Magic();
MagicMatch match = magic.getMagicMatch(file, false);
assertEquals(match.getMimeType(), "image/png");
}
这个库可以处理数据流,因此不需要文件存在于文件系统中。
6. 使用 Apache Tika
Apache Tika是一个工具集,可以从各种文件中检测和提取元数据和文本。它具有丰富而强大的 API,并带有我们可以使用的tika-core,用于检测文件的 MIME 类型。
让我们从配置 Maven 依赖项开始:
<dependency>
<groupId>org.apache.tika</groupId>
<artifactId>tika-core</artifactId>
<version>1.18</version>
</dependency>
接下来,我们将使用detect()方法来解析类型:
@Test
public void whenUsingTika_thenSuccess() {
File file = new File("product.png");
Tika tika = new Tika();
String mimeType = tika.detect(file);
assertEquals(mimeType, "image/png");
}
该库依赖流前缀中的魔法标记来进行类型解析。
7. 结论
在本文中,我们研究了获取文件 MIME 类型的各种策略。此外,我们还分析了这些方法的权衡。我们还指出了我们应该偏爱一种策略而不是另一种策略的场景。
与往常一样,本文中使用的完整源代码可在 GitHub 上获得。