Java を使用してファイルからメディア タイプ (MIME タイプ) を取得するにはどうすればよいですか? これまでのところ、JMimeMagic と Mime-Util を試しました。1 つ目はメモリ例外が発生し、2 つ目はストリームを適切に閉じません。
ファイルを調べて、その実際のタイプを (単に拡張子に基づいてではなく) 判別するにはどうすればよいでしょうか?
不運にも、
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 (ファイル拡張子とコンテンツの両方を使用する優れたライブラリ) を使用して、組み込みライブラリを超える必要があります。
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);
Apache Tikaは、ストリーム プレフィックスのマジック マーカーに基づく MIME タイプ検出をtika-coreで提供します。tika-core
他の依存関係をフェッチしないため、現在メンテナンスされていないMime Type Detection Utilityと同じくらい軽量になります。
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/1.24/detection.htmlで提供されています。
あなたが Android 開発者であれば、android.webkit.MimeTypeMap
MIME タイプをファイル拡張子に、またはその逆にマッピングするユーティリティ クラスを使用できます。
次のコード スニペットが役立つ場合があります。
private static String getMimeType(String fileUrl) {
String extension = MimeTypeMap.getFileExtensionFromUrl(fileUrl);
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
}
ローズインディア より:
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String mimeType = fileNameMap.getContentTypeFor("alert.gif");
Java 5-6 に行き詰まっている場合は、 servoy オープン ソース製品のこのユーティリティ クラスを使用してください。
この機能だけが必要です
public static String getContentType(byte[] data, String name)
コンテンツの最初のバイトをプローブし、ファイル拡張子ではなく、そのコンテンツに基づいてコンテンツ タイプを返します。
ほとんどの人が 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();
}
@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();
アパッチ・ティカ。
<!-- 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);
以下のスクリーンショット
ファイルのアップロードには 2 層の検証を使用することをお勧めします。
まず、mimeType を確認して検証できます。
次に、ファイルの最初の 4 バイトを 16 進数に変換し、それをマジック ナンバーと比較する必要があります。そうすれば、ファイルの検証を確認するための非常に安全な方法になります.
video/mp4
MIME タイプを確認するものが見つからなかったため、独自のソリューションを作成しました。00 00 00 18 66 74 79 70 69 73 6F 6D
ウィキペディアが間違っていて、ファイルの署名が正しくないことにたまたま気づきました。4 番目のバイト ( 18
) とその後のすべて70
(除外) は、それ以外の場合は有効なファイルの中でかなり多く変更されmp4
ます。
このコードは基本的にコードのコピー/貼り付けURLConnection.guessContentTypeFromStream
ですが、video/mp4
.
BufferedInputStream bis = new BufferedInputStream(new ByteArrayInputStream(content));
String mimeType = URLConnection.guessContentTypeFromStream(bis);
// Goes full barbaric and processes the bytes manually
if (mimeType == null){
// These ints converted in hex ar:
// 00 00 00 18 66 74 79 70 69 73 6F 6D
// which are the file signature (magic bytes) for .mp4 files
// from https://www.wikiwand.com/en/List_of_file_signatures
// just ctrl+f "mp4"
int[] mp4_sig = {0, 0, 0, 24, 102, 116, 121, 112};
bis.reset();
bis.mark(16);
int[] firstBytes = new int[8];
for (int i = 0; i < 8; i++) {
firstBytes[i] = bis.read();
}
// This byte doesn't matter for the file signature and changes
mp4_sig[3] = content[3];
bis.reset();
if (Arrays.equals(firstBytes, mp4_sig)){
mimeType = "video/mp4";
}
}
.mp4
10 個の異なるファイルに対して正常にテストされました。
編集:これは、多くの種類のサンプルを見つけることができる便利なリンク (まだオンラインの場合) です。私はそれらのビデオを所有しておらず、誰が所有しているのかもわかりませんが、上記のコードをテストするのに役立ちます。
春のMultipartFileファイルで。
org.springframework.web.multipart.MultipartFile
file.getContentType();
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;
}
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'
次のコードでそれを行いました。
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){
}
}
}
他のさまざまなライブラリを試した後、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);