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


336

ほとんどの人がJavaのファイルからMIMEタイプを取得する方法を単に疑問に思っていましたか?これまでのところ、2つのユーティリティを試しました:JMimeMagicMime-Util

最初のものは私にメモリ例外を与えました、2番目はそのストリームを適切に閉じません。私は他の誰かが彼らが使用して正しく機能するメソッド/ライブラリを持っているのかと思っていましたか?


4
利用可能なライブラリの概要については、rgagnon.com
javadetails /

ここで回答として投稿されたクラスを使用しました。stackoverflow.com
Joshua Pinter

3
ティカが今の答えになるはずです。以下の他の回答は、Tikaとの多くの依存関係を明らかにしていますが、tika-coreとの依存関係はありません。
javamonkey79 '14 / 12/15

@ javamonkey79は、TIkaを使用すると、ファイルを隠蔽し、使用できなくなります。文字列contentType = tika.detect(is)。
Cool Techie 2017年

回答:


326

Java 7では、今すぐ使用できますFiles.probeContentType(path)


62
Files.probeContentType(Path)はいくつかのOSでバグがあり、多くのバグレポートが提出されていることに注意してください。ubuntuで動作するソフトウェアに問題がありましたが、Windowsでは失敗しました。Windowsでは、Files.probeContentType(Path)は常にnullを返したようです。私のシステムではなかったので、JREやWindowsのバージョンを確認しませんでした。それはおそらくJava 7用のOracle JREを備えたWindows 7または8でした
シルバー

13
私はOS X 10.9上で動作していると私は取得nullのために.xml.png.xhtmlファイル。私がひどく間違っていることをしているのかどうかはわかりませんが、それはかなりひどいようです。

36
これに関する主な制限は、ファイルがファイルシステム上に存在する必要があることです。これは、ストリームまたはバイト配列などでは動作しません
Necreaux

3
名前から拡張子を削除すると、このメソッドはMIMEタイプを返すことができません。例として、名前がtest.mp4の場合は「test」に変更し、メソッドはnullを返します。また、映画の拡張子をpngなどに変更すると、PNG MIMEタイプが返されます
Sarkhan

10
これは、ファイルに拡張子がないか間違っている場合は役に立ちません。
shmosel

215

残念ながら、

mimeType = file.toURL().openConnection().getContentType();

このURLを使用するとファイルがロックされたままになるため、機能しません。たとえば、削除できなくなります。

しかし、あなたはこれを持っています:

mimeType= URLConnection.guessContentTypeFromName(file.getName());

さらに、ファイル拡張子の単なる使用を超えた利点があり、コンテンツをのぞくことができます。

InputStream is = new BufferedInputStream(new FileInputStream(file));
mimeType = URLConnection.guessContentTypeFromStream(is);
 //...close stream

ただし、上記のコメントで示唆されているように、MIMEタイプの組み込みテーブルは非常に制限されており、MSWordやPDFなどは含まれません。したがって、一般化したい場合は、たとえばMime-Util(ファイル拡張子とコンテンツの両方を使用する優れたライブラリ)を使用して、組み込みライブラリを超える必要があります。


8
完璧な解決策-私を大いに助けてくれました!包装FileInputStreamBufferedInputStream別段-重要な部分であるguessContentTypeFromStream戻りnull(渡されたInputStreamインスタンスは、マークをサポートしなければならない)
ユーリNakonechnyy

11
ハワーバーにURLConnectionは、認識できるコンテンツタイプのセットが非常に限られています。たとえば、検出できませんapplication/pdf
kpentchev 2013

3
あなたはそれを閉じる方法がないので、それはそれをロックしたままにするだけです。URLConnectionを切断すると、ロックが解除されます。
ローンの侯爵2014年

1
guessContentTypeFromStreamとguessContentTypeFromNameの両方が認識されない(例:mp4
Hartmut P.

3
guessContentTypeFromName()デフォルトの$JAVA_HOME/lib/content-types.propertiesファイルを使用します。システムプロパティを変更することで、独自の拡張ファイルを追加できますSystem.setProperty("content.types.user.table","/lib/path/to/your/property/file");
Rasika Perera '30

50

JAF APIはJDK 6の一部ですjavax.activation。パッケージを見てください。

最も興味深いクラスはjavax.activation.MimeType-実際のMIMEタイプホルダー-およびjavax.activation.MimetypesFileTypeMap-ファイルの文字列としてMIMEタイプを解決できるインスタンスを持つクラスです。

String fileName = "/path/to/file";
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();

// only by file name
String mimeType = mimeTypesMap.getContentType(fileName);

// or by actual File instance
File file = new File(fileName);
mimeType = mimeTypesMap.getContentType(file);

4
残念ながら、getContentType(File)状態のjavadocとして:ファイルオブジェクトのMIMEタイプを返しますgetContentType(f.getName())。このクラスの実装はを呼び出します 。
Matyas

3
また、META-INF / mime.typesファイルを使用してこの機能を拡張できるため、Java 6を使用せざるを得ない場合に最適です。docs.oracle.com
javaee

8
新しいオブジェクトの作成はスキップできますMimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(file)
akostadinov

ご回答有難うございます。うまくいきました。
Radadiya Nikunj

ただし、ファイル名だけに基づいてコンテンツタイプを返します。これは、ユーザーがアップロードしたファイルでは特に危険です。
Sergey Ponomarev

47

Apacheのティカあなただけの必要な3行のコードを

File file = new File("/path/to/file");
Tika tika = new Tika();
System.out.println(tika.detect(file));

groovyコンソールを使用している場合は、次のコードを貼り付けて実行するだけです。

@Grab('org.apache.tika:tika-core:1.14')
import org.apache.tika.Tika;

def tika = new Tika()
def file = new File("/path/to/file")
println tika.detect(file)

APIは豊富で、「何でも」解析できることに注意してください。tika-core 1.14の時点で、次のものがあります。

String  detect(byte[] prefix)
String  detect(byte[] prefix, String name)
String  detect(File file)
String  detect(InputStream stream)
String  detect(InputStream stream, Metadata metadata)
String  detect(InputStream stream, String name)
String  detect(Path path)
String  detect(String name)
String  detect(URL url)

詳細については、apidocsを参照しください。


1
csvでは機能しません。wtf?stackoverflow.com/questions/46960231/...
gstackoverflow

1
Tikaの悪い点の1つは、依存関係の肥大化です。それは私のjarのサイズを54MB増やしました!!!
ヘルミー、

1
@helmyTika 1.17はスタンドアロンで、サイズはわずか648 KBです。
サイナン

...またはnew Tika().detect(file.toPath())ファイルのコンテンツに基づく検出ではなく、ファイルの拡張子ベースの検出のみ
Lu55

@ Lu55ドキュメントはまだドキュメントのコンテンツを使用していると言います。私はあなたが意味を考えるnew Tika().detect(file.getPath())だけで、ファイル拡張子を使用する、
delucasvb

31

Apache Tikaは、tika-coreで、ストリームプレフィックスのマジックマーカーに基づくMIMEタイプの検出を提供します。tika-coreは他の依存関係を取得しないため、現在メンテナンスされていないMIMEタイプ検出ユーティリティと同じくらい軽量になります

変数theInputStreamを使用した単純なコード例(Java 7)およびtheFileName

try (InputStream is = theInputStream;
        BufferedInputStream bis = new BufferedInputStream(is);) {
    AutoDetectParser parser = new AutoDetectParser();
    Detector detector = parser.getDetector();
    Metadata md = new Metadata();
    md.add(Metadata.RESOURCE_NAME_KEY, theFileName);
    MediaType mediaType = detector.detect(bis, md);
    return mediaType.toString();
}

MediaType.detect(...)は直接使用できないことに注意してください(TIKA-1120)。より多くのヒントがhttps://tika.apache.org/0.10/detection.htmlで提供されています


1
+1またMetadata.RESOURCE_NAME_KEY、省略しても構いませんが(元の名前がない場合や、元の名前に依存できない場合)、その場合、場合によっては間違った結果が得られます(たとえば、オフィス文書)。
user1516873 2017

ファイル名に拡張子がない場合、XLSXの検出にいくつかの問題があります...しかし、このソリューションはシンプルでエレガントです。
オスカーペレス

23

Android開発者であれば、android.webkit.MimeTypeMapMIMEタイプをファイル拡張子に、またはその逆にマップするユーティリティクラスを使用できます。

次のコードスニペットが役立つ場合があります。

private static String getMimeType(String fileUrl) {
    String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
    return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}

3
これは、「/ sdcard / path / to / video.extension」などのローカルファイルパスで試した場合にも機能します。問題は、ローカルファイルのパスにスペースが含まれている場合、常にnullを返す
nmxprime

17

roseindiaから:

FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");

7
回答に反対票を投じた人がいれば、コメントを追加してください。そうすれば、私(および他の人)はより良い回答を投稿できるようになります。
AlikElzin-kilaka 2013年

3
私はあなたに反対票を投じませんでしたが、getFileNameMapは 'bmp'などの多くの基本的なファイルタイプでは機能しません。また、URLConnection.guessContentTypeFromNameは同じものを返します
Ovidiu Buligan

5
非常に不完全な機能。Java 7以降、html、pdf、およびjpeg拡張機能は正しいMIMEタイプを返しますが、jsおよびcssはnullを返します。
djsumdog 2014

「webm」でテストしたところ、nullが返されました。
Henrique Rocha

16

あなたがJava 5-6で立ち往生しているならサーボオープンソース製品のこのユーティリティクラス。

この機能だけが必要です

public static String getContentType(byte[] data, String name)

コンテンツの最初のバイトを調べ、ファイル拡張子ではなく、そのコンテンツに基づいてコンテンツタイプを返します。


シンプルで人気のある、私が必要とするいくつかのファイルタイプに対応しました:)
user489041

13

ほとんどの人がJavaのファイルからMIMEタイプを取得する方法を単に疑問に思っていましたか?

ファイルとバイト配列からコンテンツタイプ(MIMEタイプ)を判別できるSimpleMagic Javaパッケージを公開しました。ほとんどの〜Unix OS構成の一部であるUnix file(1)コマンドマジックファイルを読み取って実行するように設計されています。

私はApache Tikaを試してみましたが、依存関係が非常に大きく、URLConnectionファイルのバイトを使用せずMimetypesFileTypeMap、ファイル名だけを調べています。

SimpleMagicを使用すると、次のようなことができます。

// create a magic utility using the internal magic file
ContentInfoUtil util = new ContentInfoUtil();
// if you want to use a different config file(s), you can load them by hand:
// ContentInfoUtil util = new ContentInfoUtil("/etc/magic");
...
ContentInfo info = util.findMatch("/tmp/upload.tmp");
// or
ContentInfo info = util.findMatch(inputStream);
// or
ContentInfo info = util.findMatch(contentByteArray);

// null if no match
if (info != null) {
   String mimeType = info.getMimeType();
}

1
複数の画像ファイルでテストしました。すべての拡張子が変更されました。あなたの素晴らしいライブラリはそれを適切に処理しました。もちろんその光も:)。
saurabheights

1
はい、これはうまくいきます。そして、Android内でこのソリューションを使用する必要がある場合は、build.gradleファイルに次の行を含めるだけです:compile( 'com.j256.simplemagic:simplemagic:1.10')
jkincali

1
これは素晴らしいソリューションです!ありがとう!
javydreamercsw 2017

5

私の5セントでチップを入れるには:

TL、DR

私はMimetypesFileTypeMapを使用して、そこにないMIMEを追加し、特に必要な場合は、Mime.typesファイルに追加します。

そして今、長い読み:

まず第一に、MIMEタイプのリストは膨大です。ここを参照してください:https : //www.iana.org/assignments/media-types/media-types.xhtml

私は最初にJDKが提供する標準機能を使用したいのですが、それがうまくいかない場合は、他の方法を探します。

ファイル拡張子からファイルタイプを判別する

1.6以降、Javaには上記の回答の1つで指摘されているようにMimetypesFileTypeMapがあり、MIMEタイプを判別する最も簡単な方法です。

new MimetypesFileTypeMap().getContentType( fileName );

通常の実装では、これはあまり機能しません(つまり、.htmlでは機能しますが、.pngでは機能しません)。ただし、必要なコンテンツタイプを追加するのは非常に簡単です。

  1. プロジェクトのMETA-INFフォルダーに「mime.types」という名前のファイルを作成します
  2. 必要なすべてのMIMEタイプに対して行を追加します。デフォルトの実装では提供されていません(何百ものMIMEタイプがあり、時間が経つにつれてリストが大きくなります)。

pngおよびjsファイルのエントリの例は次のとおりです。

image/png png PNG
application/javascript js

mime.typesファイル形式について詳しくは、https//docs.oracle.com/javase/7/docs/api/javax/activation/MimetypesFileTypeMap.htmlをご覧ください。

ファイルの内容からファイルの種類を判別する

1.7以降、Javaにはjava.nio.file.spi.FileTypeDetectorがあり、実装固有の方法でファイルタイプを決定するための標準APIを定義しています。

ファイルのMIMEタイプをフェッチするには、単にFilesを使用して、コードで次のようにします。

Files.probeContentType(Paths.get("either file name or full path goes here"));

API定義は、ファイル名またはファイルコンテンツ(マジックバイト)からファイルMIMEタイプを判別するための機能を提供します。このため、probeContentType()メソッドはIOExceptionをスローします。このAPIの実装がそれに提供されたパスを使用して、関連付けられているファイルを実際に開こうとした場合です。

繰り返しますが、これ(JDKに付属するもの)のバニラ実装では、多くのことが望まれます。

はるか遠くにある銀河系の理想的な世界では、このファイルからMIMEタイプへの問題を解決しようとするこれらのすべてのライブラリーは、単にjava.nio.file.spi.FileTypeDetectorを実装するだけであり、優先する実装ライブラリーのjarをドロップします。あなたのクラスパスにファイルを入れれば、それだけです。

TL、DRセクションが必要な実世界では、名前の横に星が最も多いライブラリを見つけて使用する必要があります。この特定のケースでは、(まだ;)は必要ありません。


3

@Joshua Foxが最初に言った方法を含め、いくつかの方法を試しました。しかし、PDFファイルなどの頻繁なMIMEタイプを認識しないものもあれば、偽のファイルで信頼できないものもあります(拡張子をTIFに変更したRARファイルで試しました)。私が見つけた解決策は、@ Joshua Foxが表面的に言っているように、次のようにMimeUtil2を使用することです

MimeUtil2 mimeUtil = new MimeUtil2();
mimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
String mimeType = MimeUtil2.getMostSpecificMimeType(mimeUtil.getMimeTypes(file)).toString();

5
MimeUtil2ではまったく成功しませんでした。ほとんどすべてがアプリケーション/オクテットストリームとして返されました。MimeUtil.getMimeTypes()を使用して、 `MimeUtil.registerMimeDetector(" eu.medsea.mimeutil.detector.MagicMimeMimeDetector ");で初期化した後、はるかに成功しました。MimeUtil.registerMimeDetector( "eu.medsea.mimeutil.detector.ExtensionMimeDetector"); MimeUtil.registerMimeDetector( "eu.medsea.mimeutil.detector.OpendesktopMimeDetector"); `
ブライアンピパ

2
実用的なソリューションをありがとう。mime-utilのドキュメントでは、ユーティリティクラスをインスタンス化する方法があまり明確ではありません。最後にそれを立ち上げて実行しましたが、クラス名文字列を実際のクラスに置き換えました。MimeUtil.registerMimeDetector(ExtensionMimeDetector.class.getName()); 文字列mimeType = MimeUtil.getMostSpecificMimeType(MimeUtil.getMimeTypes(filename))。toString();
Rob Juurlink 2013年

2

ファイルのアップロードには2層検証を使用することをお勧めします。

最初に、mimeTypeを確認して検証できます。

次に、ファイルの最初の4バイトを16進数に変換してから、マジックナンバーと比較する必要があります。そうすれば、ファイルの検証をチェックする本当に安全な方法になります。


2

これは私がこれを行うために見つけた最も簡単な方法です:

byte[] byteArray = ...
InputStream is = new BufferedInputStream(new ByteArrayInputStream(byteArray));
String mimeType = URLConnection.guessContentTypeFromStream(is);

最高のソリューション!
Sherzod

2

サーブレットを使用していて、サーブレットコンテキストを使用できる場合は、次のコマンドを使用できます。

getServletContext().getMimeType( fileName );

1
なにgetServletContext
e-info128


0

Linux OSで作業している場合は、コマンドラインがありfile --mimetypeます。

String mimetype(file){

   //1. run cmd
   Object cmd=Runtime.getRuntime().exec("file --mime-type "+file);

   //2 get output of cmd , then 
    //3. parse mimetype
    if(output){return output.split(":")[1].trim(); }
    return "";
}

その後

mimetype("/home/nyapp.war") //  'application/zip'

mimetype("/var/www/ggg/au.mp3") //  'audio/mp3'

2
これは機能しますが、コードを特定のOSに結び付け、それを実行するシステムに外部ユーティリティが存在する必要があるため、IMOは悪い習慣です。誤解しないでください。それは完全に有効なソリューションですが、移植性を
損ない

@ToVine:記録のために、私は敬意を払って意見を異にします。すべてのJavaプログラムが移植可能である必要はありません。コンテキストとプログラマーにその決定をさせましょう。en.wikipedia.org/wiki/Java_Native_Interface
Zahnon

0

他のさまざまなライブラリを試した後、mime-utilで解決しました。

<groupId>eu.medsea.mimeutil</groupId>
      <artifactId>mime-util</artifactId>
      <version>2.1.3</version>
</dependency>

File file = new File("D:/test.tif");
MimeUtil.registerMimeDetector("eu.medsea.mimeutil.detector.MagicMimeMimeDetector");
Collection<?> mimeTypes = MimeUtil.getMimeTypes(file);
System.out.println(mimeTypes);

0
public String getFileContentType(String fileName) {
    String fileType = "Undetermined";
    final File file = new File(fileName);
    try
    {
        fileType = Files.probeContentType(file.toPath());
    }
    catch (IOException ioException)
    {
        System.out.println(
                "ERROR: Unable to determine file type for " + fileName
                        + " due to exception " + ioException);
    }
    return fileType;
}

このメソッドFiles.probeContentType(String)はJDKバージョン1.7以降で使用でき、私には非常に便利です。
Reza Rahimi 2017年

おかげで、なぜ一部のユーザーが反対票を投じたのか理解できません)))
Vazgen Torosyan 2017年

まったくそうではないかもしれませんが、JDKの以前のバージョンがインストールされている可能性があります:)))
Reza Rahimi

0

これは、MimetypesFileTypeMap()。getContentType(new File( "filename.ext"))の 1行で実行できます 。完全なテストコードを見てください(Java 7):

import java.io.File;
import javax.activation.MimetypesFileTypeMap;
public class MimeTest {
    public static void main(String a[]){
         System.out.println(new MimetypesFileTypeMap().getContentType(
           new File("/path/filename.txt")));
    }
}

このコードは次の出力を生成します:text / plain


0
File file = new File(PropertiesReader.FILE_PATH);
MimetypesFileTypeMap fileTypeMap = new MimetypesFileTypeMap();
String mimeType = fileTypeMap.getContentType(file);
URLConnection uconnection = file.toURL().openConnection();
mimeType = uconnection.getContentType();

4
このコードは問題を解決する可能性がありますが、説明を含めると、投稿の品質を向上させるのに役立ちます。
シュリー

0

私は次のコードでそれをしました。

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MimeFileType {

    public static void main(String args[]){

        try{
            URL url = new URL ("https://www.url.com.pdf");

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setDoOutput(true);
            InputStream content = (InputStream)connection.getInputStream();
            connection.getHeaderField("Content-Type");

            System.out.println("Content-Type "+ connection.getHeaderField("Content-Type"));

            BufferedReader in = new BufferedReader (new InputStreamReader(content));

        }catch (Exception e){

        }
    }
}

0

アパッチティカ。

<!-- https://mvnrepository.com/artifact/org.apache.tika/tika-parsers -->
<dependency>
    <groupId>org.apache.tika</groupId>
    <artifactId>tika-parsers</artifactId>
    <version>1.24</version>
</dependency>

および2行のコード。

Tika tika=new Tika();
tika.detect(inputStream);

下のスクリーンショット

ここに画像の説明を入力してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.