如何检查上传的文件是图片还是其他文件?

新手上路,请多包涵

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

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

我该如何检查 BufferedImage ,它是否真的是图像或其他东西?

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

原文由 user405398 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 501
2 个回答

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

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

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

 <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.
    }
}

但是,如果您还想涵盖更多图像类型,请考虑使用第 3 方库,它通过嗅探 文件 头来完成所有工作。例如支持 BMP、GIF、JPG、PNG、TIF 和 PSD(但不支持 SVG)的 JMimeMagicApache TikaApache 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() 将上传的图像保存到磁盘。 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 在 servlet 应用程序中保存上传文件的推荐方法

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

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

原文由 BalusC 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

原文由 gagan bopanna 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题