私の Web アプリケーションには、画像アップロード モジュールがあります。アップロードしたファイルが画像ファイルなのか、それ以外のファイルなのかを確認したい。サーバー側でJavaを使用しています。
画像はJavaのように読み取られBufferedImage
、次にそれをディスクに書き込んでいますImageIO.write()
BufferedImage
それが本当に画像なのか、それとも何か他のものなのか、どのように確認すればよいですか?
提案やリンクをいただければ幸いです。
私の Web アプリケーションには、画像アップロード モジュールがあります。アップロードしたファイルが画像ファイルなのか、それ以外のファイルなのかを確認したい。サーバー側でJavaを使用しています。
画像はJavaのように読み取られBufferedImage
、次にそれをディスクに書き込んでいますImageIO.write()
BufferedImage
それが本当に画像なのか、それとも何か他のものなのか、どのように確認すればよいですか?
提案やリンクをいただければ幸いです。
これをサーブレットコンテキストで実行していると仮定しています。ファイル拡張子だけに基づいてコンテンツ タイプをチェックする余裕がある場合は、 を使用ServletContext#getMimeType()
して MIME タイプ (コンテンツ タイプ) を取得します。で始まるかどうかを確認してくださいimage/
。
String fileName = uploadedFile.getFileName();
String mimeType = getServletContext().getMimeType(fileName);
if (mimeType.startsWith("image/")) {
// It's an image.
}
デフォルトの MIME タイプはweb.xml
、問題の servletcontainer の で定義されています。たとえば、Tomcat では、/conf/web.xml
. /WEB-INF/web.xml
次のように、webappで拡張/オーバーライドできます。
<mime-mapping>
<extension>svg</extension>
<mime-type>image/svg+xml</mime-type>
</mime-mapping>
しかし、これは、ファイル拡張子を変更してあなたを欺くユーザーを防ぐものではありません。これもカバーしたい場合は、実際のファイルの内容に基づいて MIME タイプを決定することもできます。BMP、GIF、JPG、または PNG タイプ (ただし、TIF、PSD、SVG などは除く) のみをチェックする余裕がある場合は、それを直接フィードしてImageIO#read()
、例外がスローされないかどうかをチェックできます。
try (InputStream input = uploadedFile.getInputStream()) {
try {
ImageIO.read(input).toString();
// It's an image (only BMP, GIF, JPG and PNG are recognized).
} catch (Exception e) {
// It's not an image.
}
}
ただし、より多くの画像タイプもカバーしたい場合は、ファイル ヘッダーをスニッフィングすることですべての作業を行うサードパーティ ライブラリの使用を検討してください。たとえば、BMP、GIF、JPG、PNG、TIF、および PSD の両方をサポートするJMimeMagicまたはApache Tika (ただし、SVG はサポートしません)。Apache Batikは SVG をサポートしています。以下の例では、JMimeMagic を使用しています。
try (InputStream input = uploadedFile.getInputStream()) {
String mimeType = Magic.getMagicMatch(input, false).getMimeType();
if (mimeType.startsWith("image/")) {
// It's an image.
} else {
// It's not an image.
}
}
必要に応じて組み合わせを使用し、どちらかを上回ることができます。
ImageIO#write()
とはいえ、アップロードした画像を必ずしもディスクに保存する必要はありません。取得したものを通常の Java IO の方法で aまたは anyInputStream
に直接書き込むだけで十分です (アップロードされたファイルをサーブレット アプリケーションに保存するための推奨される方法も参照してください)。Path
OutputStream
FileOutputStream
try (InputStream input = uploadedFile.getInputStream()) {
Files.copy(input, new File(uploadFolder, fileName).toPath());
}
もちろん、サイズなどの画像情報を収集したり、操作(トリミング/サイズ変更/回転/変換/など)したい場合を除きます。
私の場合、 org.apache.commons.imaging.Imagingを使用しました。以下は、画像が jpeg 画像かどうかを確認するサンプル コードです。アップロードされたファイルが画像でない場合、ImageReadException をスローします。
try {
//image is InputStream
byte[] byteArray = IOUtils.toByteArray(image);
ImageFormat mimeType = Imaging.guessFormat(byteArray);
if (mimeType == ImageFormats.JPEG) {
return;
} else {
// handle image of different format. Ex: PNG
}
} catch (ImageReadException e) {
//not an image
}
これは JDK に組み込まれており、単純に次をサポートするストリームが必要です。
byte[] data = ;
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
String mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream