Java 如何检查上传的文件是图片还是其他文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4169713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check a uploaded file whether it is an image or other file?
提问by
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.
在我的 Web 应用程序中,我有一个图像上传模块。我想检查上传的文件是图像文件还是任何其他文件。我在服务器端使用 Java。
The image is read as BufferedImage
in java and then I am writing it to disk with ImageIO.write()
图像BufferedImage
在 java 中读取,然后我将它写入磁盘ImageIO.write()
How shall I check the BufferedImage
, whether it's really an image or something else?
我应该如何检查BufferedImage
,它是否真的是图像还是其他东西?
Any suggestions or links would be appreciated.
任何建议或链接将不胜感激。
采纳答案by BalusC
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/
.
我假设您在 servlet 上下文中运行它。如果仅根据文件扩展名检查内容类型是负担得起的,则使用ServletContext#getMimeType()
获取 mime 类型(内容类型)。只需检查它是否以image/
.
String fileName = uploadedFile.getFileName();
String mimeType = getServletContext().getMimeType(fileName);
if (mimeType.startsWith("image/")) {
// It's 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 类型在web.xml
相关 servletcontainer 中定义。例如,在 Tomcat 中,它位于/conf/web.xml
. 你可以在/WEB-INF/web.xml
你的 webapp 中扩展/覆盖它,如下所示:
<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 actualfile content. If it's affordable to check for only BMP, GIF, JPG or PNG types (but not TIF, PSD, SVG, etc), then you can just feed it directly to ImageIO#read()
and check if it doesn't throw an exception.
但这并不能阻止用户通过更改文件扩展名来欺骗您。如果您也想涵盖这一点,那么您还可以根据实际文件内容确定 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.
}
}
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 headers. For example JMimeMagicor Apache Tikawhich support both BMP, GIF, JPG, PNG, TIF and PSD (but not SVG). Apache Batiksupports SVG. Below example uses JMimeMagic:
但是,如果您还想涵盖更多图像类型,请考虑使用 3rd 方库,它通过嗅探文件头来完成所有工作。例如,支持 BMP、GIF、JPG、PNG、TIF 和 PSD(但不支持 SVG)的JMimeMagic或Apache Tika。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.
}
}
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):
也就是说,您不一定需要ImageIO#write()
将上传的图像保存到磁盘。只需将获得的InputStream
直接写入aPath
或任何OutputStream
类似于FileOutputStream
通常的 Java IO 方式就足够了(另请参阅在 servlet 应用程序中保存上传文件的推荐方式):
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.
除非你想收集一些图像信息,比如它的尺寸和/或想要操纵它(裁剪/调整大小/旋转/转换/等)当然。
回答by gagan bopanna
I used org.apache.commons.imaging.Imagingin 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.
在我的例子中,我使用了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
}
回答by gcstang
This is built into the JDK and simply requires a stream with support for
这是内置于 JDK 中的,只需要一个支持
byte[] data = ;
InputStream is = new BufferedInputStream(new ByteArrayInputStream(data));
String mimeType = URLConnection.guessContentTypeFromStream(is);
//...close stream
回答by Safwan Muhammed
Try using multipart file instead of BufferedImage
尝试使用多部分文件而不是 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");
}
}