JavaでファイルのMIMEタイプを取得する

JavaでファイルのMIMEタイプを取得する

1. 概要

このチュートリアルでは、ファイルのMIMEタイプを取得するためのさまざまな戦略を見ていきます。 該当する場合は、戦略で使用可能なMIMEタイプを拡張する方法を検討します。

また、ある戦略を他の戦略よりも優先すべき場所についても指摘します。

2. Java 7を使用する

Java 7から始めましょう。これは、MIMEタイプを解決するためのメソッドFiles.probeContentType(path)を提供します。

@Test
public void whenUsingJava7_thenSuccess() {
    Path path = new File("product.png").toPath();
    String mimeType = Files.probeContentType(path);

    assertEquals(mimeType, "image/png");
}

このメソッドは、インストールされたFileTypeDetector実装を利用してMIMEタイプをプローブします。 各実装のprobeContentTypeを呼び出して、タイプを解決します。

これで、ファイルが実装のいずれかで認識されると、コンテンツタイプが返されます。 ただし、それが起こらない場合は、システムのデフォルトのファイルタイプ検出機能が呼び出されます。

ただし、デフォルトの実装はOS固有であり、使用しているOSによっては失敗する可能性があります。

それに加えて、ファイルがファイルシステムに存在しない場合、戦略は失敗することに注意することも重要です。 さらに、ファイルに拡張子がない場合、失敗します。

 3. URLConnectionの使用

URLConnectionは、ファイルのMIMEタイプを検出するためのいくつかのAPIを提供します。 それぞれについて簡単に見ていきましょう。

3.1. getContentType()の使用

URLConnectiongetContentType()メソッドを使用して、ファイルの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");
}

ただし、このアプローチの主な欠点は、it’s very slowであるということです。

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からresolve the MIME type from the extensionを利用します。

代わりに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タイプの組み込みテーブルは非常に制限されています。

デフォルトでは、the class uses content-types.propertiesファイルはJRE_HOME/libにあります。 We can, however, extend it, by specifying a user-specific table using the content.types.user.table property:

System.setProperty("content.types.user.table","");

4. MimeTypesFileTypeMapの使用

MimeTypesFileTypeMapは、ファイルの拡張子を使用してMIMEタイプを解決します。 このクラスはJava6に付属しているため、JDK1.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. /lib/mime.types

  4. META-INF/mime.typesという名前のリソース

  5. META-INF/mimetypes.defaultという名前のリソース(通常はactivation.jarファイルにのみあります)

ただし、ファイルが見つからない場合は、応答としてapplication/octet-streamが返されます。

5. jMimeMagicの使用

jMimeMagicは、ファイルのMIMEタイプを取得するために使用できる制限付きライセンスのライブラリです。

Mavenの依存関係を構成することから始めましょう:


    net.sf.jmimemagic
    jmimemagic
    0.1.5

このライブラリの最新バージョンは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. ApacheTikaの使用

Apache Tikaは、さまざまなファイルからメタデータとテキストを検出して抽出するツールセットです。 豊富で強力なAPIがあり、ファイルのMIMEタイプを検出するために使用できるtika-coreが付属しています。

Mavenの依存関係を構成することから始めましょう:


    org.apache.tika
    tika-core
    1.18

次に、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タイプを取得するためのさまざまな戦略について説明しました。 さらに、アプローチのトレードオフも分析しました。 また、ある戦略を他の戦略よりも優先すべきシナリオを指摘しました。

この記事で使用されている完全なソースコードは、いつものようにover at GitHubで入手できます。