Подтвердить что ты не робот

Как проверить загруженный файл, будь то изображение или другой файл?

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

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

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

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

4b9b3361

Ответ 1

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

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

Тип mime по умолчанию определяется в web.xml рассматриваемого сервлетконтейнера. Например, в 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 an image (only BMP, GIF, JPG and PNG are recognized).
    } catch (Exception e) {
        // It 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 an image.
    } else {
        // It not an image.
    }
}

При необходимости вы можете использовать комбинации и перевешивать одно и другое.

Тем не менее вам не нужно ImageIO#write() сохранять загруженное изображение на диск. Просто записывая полученный InputStream непосредственно в Path или любой OutputStream как FileOutputStream, обычный способ Java IO более чем достаточен (см. Также Рекомендуемый способ сохранения загруженных файлов в приложении сервлета):

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

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

Ответ 2

Я использовал 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
    }

Ответ 3

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

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