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

时间:2010-11-12 22:39:35

标签: java image servlets file-upload bufferedimage

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

图像在java中读作BufferedImage,然后我用ImageIO.write()

将其写入磁盘

如何查看BufferedImage,无论是图像还是其他内容?

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

4 个答案:

答案 0 :(得分:90)

我假设你在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。您可以在网络应用的/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.
    }
}

但是,如果您想要覆盖更多图像类型,请考虑使用第三方库,通过嗅探file headers来完成所有工作。例如JMimeMagicApache 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 IO方式就足够了(另请参阅Recommended way to save uploaded files in a servlet application):< / p>

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

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

答案 1 :(得分:3)

我在案件中使用了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 :(得分:2)

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

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

答案 3 :(得分:0)

尝试使用分段文件而不是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");
                 }
      }