1. 概述

MIME类型是一种标签,用于指定互联网上数据的类型和格式。*一个MIME类型可以关联多个文件扩展名。例如,“image/jpeg*" MIME类型就包括“.jpg”、“.jpeg”或“.jpe”这样的扩展名。**

在这篇教程中,我们将探讨在Java中确定特定MIME类型的文件扩展名的不同方法。我们将重点关注四种主要的解决方案。

我们的部分实现会包含可选的扩展名末尾点。例如,如果我们的MIME类型名称是“image/jpeg”,那么字符串“jpg”或“*.jpg*”都将作为文件的扩展名返回。

2. 使用Apache Tika

Apache Tika 是一个工具包,用于检测和提取各种文件的元数据和文本。它提供了一个丰富且强大的API,可以用来检测MIME类型的文件扩展名。

首先,我们配置Maven的依赖项:

<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-core</artifactId>
    <version>2.9.0</version>
</dependency>

如前所述,一个MIME类型可能有多个扩展名。为此,MimeType类提供了两个不同的方法:getExtension()getExtensions()

getExtension()方法返回首选的文件扩展名,而getExtensions()方法返回该MIME类型的已知所有扩展名列表。

接下来,我们将使用MimeType类的这两个方法来获取扩展名:

@Test
public void whenUsingTika_thenGetFileExtension() {
    List<String> expectedExtensions = Arrays.asList(".jpg", ".jpeg", ".jpe", ".jif", ".jfif", ".jfi");
    MimeTypes allTypes = MimeTypes.getDefaultMimeTypes();
    MimeType type = allTypes.forName("image/jpeg");
    String primaryExtension = type.getExtension();
    assertEquals(".jpg", primaryExtension);
    List<String> detectedExtensions = type.getExtensions();
    assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
}

3. 使用Jodd Util

我们可以选择使用Jodd Util库,它包含一个用于查找MIME类型文件扩展名的工具。

首先,添加Maven的依赖项:

<dependency>
    <groupId>org.jodd</groupId>
     <artifactId>jodd-util</artifactId>
    <version>6.2.1</version>
</dependency>

然后,我们将使用findExtensionsByMimeTypes()方法获取所有支持的文件扩展名

@Test
public void whenUsingJodd_thenGetFileExtension() {
    List<String> expectedExtensions = Arrays.asList("jpeg", "jpg", "jpe");
    String[] detectedExtensions = MimeTypes.findExtensionsByMimeTypes("image/jpeg", false);
    assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
}

Jodd Util提供的文件类型和扩展名有限。它更注重简洁而非全面覆盖。

findExtensionsByMimeTypes()方法中,我们可以通过设置第二个布尔参数为true来激活通配符模式。当提供通配符模式作为MIME类型时,我们将获取与指定模式匹配的所有MIME类型的扩展名。

例如,当我们设置MIME类型为image/\**并启用通配符模式时,我们将获取image类别下的所有MIME类型的扩展名。

4. 使用SimpleMagic

SimpleMagic 是一个主要用于文件MIME类型检测的实用包。它还包含将MIME类型转换为文件扩展名的方法。

首先,添加Maven的依赖项:

<dependency>
    <groupId>com.j256.simplemagic</groupId>
    <artifactId>simplemagic</artifactId>
    <version>1.17</version>
</dependency>

现在,我们将使用ContentInfo类的getFileExtensions()方法获取所有支持的文件扩展名

@Test
public void whenUsingSimpleMagic_thenGetFileExtension() {
    List<String> expectedExtensions = Arrays.asList("jpeg", "jpg", "jpe");
    String[] detectedExtensions = ContentType.fromMimeType("image/jpeg").getFileExtensions();
    assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
}

SimpleMagic库中有一个名为ContentType的枚举,其中包含了MIME类型及其对应文件扩展名和简单名称的映射。getFileExtensions()方法利用这个枚举,根据提供的MIME类型获取文件扩展名。

5. 使用自定义MIME类型到扩展名的映射

我们也可以不依赖外部库,从MIME类型获取文件扩展名。我们将创建一个名为mimeToExtensionMap的自定义映射,将MIME类型与其对应的文件扩展名关联起来。**get()方法允许我们在映射中查找并返回提供MIME类型的预配置文件扩展名:**

@Test
public void whenUsingCustomMap_thenGetFileExtension() {
    Map<String, Set<String>> mimeToExtensionMap = new HashMap<>();
    List<String> expectedExtensions = Arrays.asList(".jpg", ".jpe", ".jpeg");
    addMimeExtensions(mimeToExtensionMap, "image/jpeg", ".jpg");
    addMimeExtensions(mimeToExtensionMap, "image/jpeg", ".jpe");
    addMimeExtensions(mimeToExtensionMap, "image/jpeg", ".jpeg");
    Set<String> detectedExtensions = mimeToExtensionMap.get("image/jpeg");
    assertThat(detectedExtensions).containsExactlyElementsOf(expectedExtensions);
}

void addMimeExtensions(Map<String, Set> map, String mimeType, String extension) {
    map.computeIfAbsent(mimeType, k-> new HashSet<>()).add(extension);
}

示例映射包含一些例子,但可以根据需要轻松添加更多的映射。

6. 总结

在这篇文章中,我们探讨了从MIME类型提取文件扩展名的不同方法。我们考察了两种不同的方法:利用现有的库和针对特定需求定制的自定义逻辑。

对于有限的MIME类型集,自定义逻辑是一种选择,尽管它可能带来维护挑战。另一方面,像Apache Tika或Jodd Util这样的库提供了广泛的MIME类型覆盖和易用性,使其成为处理各种MIME类型的可靠选择。

如往常一样,本文所使用的源代码可在GitHub上找到。