34

私の Web アプリケーションには、画像アップロード モジュールがあります。アップロードしたファイルが画像ファイルなのか、それ以外のファイルなのかを確認したい。サーバー側でJavaを使用しています。

画像はJavaのように読み取られBufferedImage、次にそれをディスクに書き込んでいますImageIO.write()

BufferedImageそれが本当に画像なのか、それとも何か他のものなのか、どのように確認すればよいですか?

提案やリンクをいただければ幸いです。

4

4 に答える 4

103

これをサーブレットコンテキストで実行していると仮定しています。ファイル拡張子だけに基づいてコンテンツ タイプをチェックする余裕がある場合は、 を使用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に直接書き込むだけで十分です (アップロードされたファイルをサーブレット アプリケーションに保存するための推奨される方法も参照してください)。PathOutputStreamFileOutputStream

try (InputStream input = uploadedFile.getInputStream()) {
    Files.copy(input, new File(uploadFolder, fileName).toPath());
}

もちろん、サイズなどの画像情報を収集したり、操作(トリミング/サイズ変更/回転/変換/など)したい場合を除きます。

于 2010-11-12T22:52:09.290 に答える
7

私の場合、 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
    }
于 2016-02-17T15:23:29.083 に答える
4

これは JDK に組み込まれており、単純に次をサポートするストリームが必要です。

byte[] data = ;
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
String mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream
于 2016-02-29T20:19:01.627 に答える