在 Java 中获取文件的 Mime 类型

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 的文件以进行类型解析。需要注意的是,该方法按特定顺序搜索文件:

  1. 以编程方式向MimetypesFileTypeMap实例添加条目
  2. . 用户主目录中的mime.types
  3. <java.home>/lib/mime.types
  4. 名为META-INF/mime.types 的资源
  5. 名为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 上获得

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值