Как проверить загруженный файл - изображение или другой файл? - PullRequest
27 голосов
/ 13 ноября 2010

В моем веб-приложении есть модуль загрузки изображений. Я хочу проверить загруженный файл, будь то файл изображения или любой другой файл. Я использую Java на стороне сервера.

Изображение читается как BufferedImage в Java, а затем я записываю его на диск с ImageIO.write()

Как мне проверить BufferedImage, действительно ли это изображение или что-то еще?

Любые предложения или ссылки будут оценены.

Ответы [ 3 ]

90 голосов
/ 13 ноября 2010

Я предполагаю, что вы запускаете это в контексте сервлета.Если можно проверить тип содержимого только по расширению файла, используйте ServletContext#getMimeType(), чтобы получить тип mime (тип содержимого).Просто проверьте, начинается ли оно с image/.

String fileName = uploadedFile.getFileName();
String mimeType = getServletContext().getMimeType(fileName);
if (mimeType.startsWith("image/")) {
    // It's an image.
}

Типы пантомимы по умолчанию определены в web.xml рассматриваемого сервлет-контейнера.Например, Tomcat находится в /conf/web.xml.Вы можете расширить / переопределить его в /WEB-INF/web.xml вашего веб-приложения следующим образом:

<mime-mapping>
    <extension>svg</extension>
    <mime-type>image/svg+xml</mime-type>
</mime-mapping>

Но это не мешает пользователям, которые обманывают вас, изменяя расширение файла.Если вы хотите охватить это, вы также можете определить тип пантомимы на основе фактического содержимого файла.Если возможно проверить только типы 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.
    }
}

Но если вы хотите охватить и другие типы изображений, подумайте об использовании сторонней библиотеки, которая выполняет всю работу, прослушивая заголовки файла .Например, JMimeMagic или Apache Tika , которые поддерживают BMP, GIF, JPG, PNG, TIF и PSD (но не 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() для сохранения загруженного изображения.на диск.Просто записать полученный InputStream непосредственно в Path или любой OutputStream, например FileOutputStream, обычный способ ввода-вывода Java более чем достаточен (см. Также Рекомендуемый способ сохранения загруженных файлов в приложении сервлета ):

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

Если вы не хотите собирать некоторую информацию об изображении, например его размеры, и / или, конечно, хотите манипулировать ею (обрезать / изменять размер / вращать / преобразовывать / и т.д.).

3 голосов
/ 17 февраля 2016

Я использовал 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
    }
2 голосов
/ 29 февраля 2016

Это встроено в JDK и просто требует потока с поддержкой

byte[] data = ;
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
String mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream
...