1概要

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

一方の戦略を他方の戦略よりも優先させるべき場所についても指摘します。


2 Java 7

を使う

Java 7から始めましょう – メソッドはhttps://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#probeContentType%28java.nio.file.Path%29[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()


を使用する

ファイルのMIMEタイプを取得するには、

URLConnection



getContentType()

メソッドを使用できます。

@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タイプのテーブルを返します。このテーブルは、入力ファイルタイプを解決するために使用されます。

MIMEタイプの組み込みテーブルは

URLConnection

に関しては非常に限られています。

デフォルトでは、

クラスは

JRE

HOME/lib

にある

content-types.properties



ファイルを使用します。 ** ただし、

content.types.user.table

__propertyを使用してユーザー固有のテーブルを指定することで拡張できます。

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>

このライブラリの最新版はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22net.sf.jmimemagic%22%20AND%20a%3A%22jmimemagic%22にあります。[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を持ち、https://search.maven.org/classic/#search%7C1%7Cg%3A%22org.apache.tika%22%20AND%20a%3A%22tika-coreが付属ファイルのMIMEタイプを検出するために利用可能な%22[tika-core]。

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

この記事で使用されている完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/core-java[over at GitHub]から入手できます。