如何判断上传的文件是图片还是其他文件?

发布于 2024-10-02 13:56:45 字数 231 浏览 6 评论 0原文

在我的网络应用程序中,我有一个图像上传模块。我想检查上传的文件是否是图像文件或任何其他文件。我在服务器端使用Java。

图像在java中被读取为BufferedImage,然后我使用ImageIO.write()将其写入磁盘,

我该如何检查BufferedImage,它到底是图像还是其他东西?

任何建议或链接将不胜感激。

In my web application I have an image uploading module. I want to check the uploaded file whether it's an image file or any other file. I am using Java in server side.

The image is read as BufferedImage in java and then I am writing it to disk with ImageIO.write()

How shall I check the BufferedImage, whether it's really an image or something else?

Any suggestions or links would be appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风吹过旳痕迹 2024-10-09 13:56:45

我假设您在 servlet 上下文中运行它。如果仅根据文件扩展名检查内容类型是可以承受的,请使用 ServletContext#getMimeType() 获取 mime 类型(内容类型)。只需检查它是否以 image/ 开头。

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

默认 mime 类型在相关 servlet 容器的 web.xml 中定义。例如,在 Tomcat 中,它位于 /conf/web.xml 中。您可以在 web 应用程序的 /WEB-INF/web.xml 中扩展/覆盖它,如下所示:

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

但这并不能阻止用户通过更改文件扩展名来欺骗您。如果您也想介绍这一点,那么您还可以根据实际文件内容确定 mime 类型。如果可以负担得起检查 仅限 BMP、GIF、JPEG、PNG、TIFF 或 WBMP 类型(但不包括 PSD、SVG 等),然后您可以直接将其提供给 ImageIO#read() 并检查它是否没有抛出异常。

try (InputStream input = uploadedFile.getInputStream()) {
    try {
        ImageIO.read(input).toString();
        // It's an image (only BMP, GIF, JPEG, PNG, TIFF and WBMP are recognized).
    } catch (Exception e) {
        // It's not an image.
    }
}

但如果您还想涵盖更多图像类型,请考虑使用第 3 方库,该库通过嗅探 文件签名。例如 Apache Tika 可以识别 ImageIO 格式 PSD、BPG、WEBP 、ICNS 和 SVG:

Tika tika = new Tika();
try (InputStream input = uploadedFile.getInputStream()) {
    String mimeType = tika.detect(input);
    if (mimeType.startsWith("image/")) {
        // It's an image.
    } else {
        // It's not an image.
    }
}

如有必要,您可以使用组合并胜过其中之一。

也就是说,您不一定需要 ImageIO#write() 将上传的图像保存到磁盘。只需将获得的InputStream直接写入Path或任何OutputStream(如FileOutputStream),通常的Java IO方式就不止如此足够(另请参阅将上传的文件保存在servlet 应用程序):

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

当然,除非您想收集一些图像信息(例如尺寸)和/或想要对其进行操作(裁剪/调整大小/旋转/转换/等)。

I'm assuming that you're running this in a servlet context. If it's affordable to check the content type based on just the file extension, then use ServletContext#getMimeType() to get the mime type (content type). Just check if it starts with image/.

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

The default mime types are definied in the web.xml of the servletcontainer in question. In for example Tomcat, it's located in /conf/web.xml. You can extend/override it in the /WEB-INF/web.xml of your webapp as follows:

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

But this doesn't prevent you from users who are fooling you by changing the file extension. If you'd like to cover this as well, then you can also determine the mime type based on the actual file content. If it's affordable to check for only BMP, GIF, JPEG, PNG, TIFF or WBMP types (but not PSD, SVG, etc), then you can just feed it directly to ImageIO#read() and check if it doesn't throw an exception.

try (InputStream input = uploadedFile.getInputStream()) {
    try {
        ImageIO.read(input).toString();
        // It's an image (only BMP, GIF, JPEG, PNG, TIFF and WBMP are recognized).
    } catch (Exception e) {
        // It's not an image.
    }
}

But if you'd like to cover more image types as well, then consider using a 3rd party library which does all the work by sniffing the file signatures. For example Apache Tika which recognizes on top of ImageIO formats also PSD, BPG, WEBP, ICNS and SVG as well:

Tika tika = new Tika();
try (InputStream input = uploadedFile.getInputStream()) {
    String mimeType = tika.detect(input);
    if (mimeType.startsWith("image/")) {
        // It's an image.
    } else {
        // It's not an image.
    }
}

You could if necessary use combinations and outweigh the one and other.

That said, you don't necessarily need ImageIO#write() to save the uploaded image to disk. Just writing the obtained InputStream directly to a Path or any OutputStream like FileOutputStream the usual Java IO way is more than sufficient (see also Recommended way to save uploaded files in a servlet application):

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

Unless you'd like to gather some image information like its dimensions and/or want to manipulate it (crop/resize/rotate/convert/etc) of course.

假装爱人 2024-10-09 13:56:45

我在我的例子中使用了 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
    }

I used org.apache.commons.imaging.Imaging in my case. Below is a sample piece of code to check if an image is a jpeg image or not. It throws ImageReadException if uploaded file is not an image.

    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
    }
吃→可爱长大的 2024-10-09 13:56:45

这是内置于 JDK 中的,只需要一个支持

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

自 Java SE 6 https://docs.oracle.com/javase/6/docs/api/java/net/URLConnection.html

This is built into the JDK and simply requires a stream with support for

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

Since Java SE 6 https://docs.oracle.com/javase/6/docs/api/java/net/URLConnection.html

败给现实 2024-10-09 13:56:45

尝试使用多部分文件而不是 BufferedImage

import org.apache.http.entity.ContentType;
...

    public void processImage(MultipartFile file) {

       if(!Arrays.asList(ContentType.IMAGE_JPEG.getMimeType(), ContentType.IMAGE_PNG.getMimeType(), ContentType.IMAGE_GIF.getMimeType()).contains(file.getContentType())) {
            throw new IllegalStateException("File must be an Image");
                 }
      }

Try using multipart file instead of BufferedImage

import org.apache.http.entity.ContentType;
...

    public void processImage(MultipartFile file) {

       if(!Arrays.asList(ContentType.IMAGE_JPEG.getMimeType(), ContentType.IMAGE_PNG.getMimeType(), ContentType.IMAGE_GIF.getMimeType()).contains(file.getContentType())) {
            throw new IllegalStateException("File must be an Image");
                 }
      }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文