测试文件是否为图像文件

Test if a file is an image file

提问人:lancegerday 提问时间:3/10/2012 最后编辑:Gerhardlancegerday 更新时间:11/12/2023 访问量:80491

问:

我正在使用一些文件,想知道是否有一种方法可以检查文件是否是图像?IO

Java 映像 文件 IO

评论

1赞 wkl 3/10/2012
stackoverflow.com/questions/670546/......(C#,但它是关于检查标头的,这不是特定于语言的),或 stackoverflow.com/questions/2192717/check-if-a-file-is-an-image,或 stackoverflow.com/questions/9244710/...

答:

62赞 Ismael Abreu 3/10/2012 #1

这对我来说效果很好。希望我能帮上忙

import javax.activation.MimetypesFileTypeMap;
import java.io.File;
class Untitled {
    public static void main(String[] args) {
        String filepath = "/the/file/path/image.jpg";
        File f = new File(filepath);
        String mimetype= new MimetypesFileTypeMap().getContentType(f);
        String type = mimetype.split("/")[0];
        if(type.equals("image"))
            System.out.println("It's an image");
        else 
            System.out.println("It's NOT an image");
    }
}

评论

0赞 Ismael Abreu 11/8/2013
嗨@dermoritz这似乎是您系统上的问题。看看这个 SO 帖子 stackoverflow.com/questions/4855627/...
0赞 WowBow 2/24/2015
如果它来自 URL 呢?在将 URL 保存到文件之前?我得到了“application/octet-stream”而不是图像。有什么想法吗?
0赞 wangqi060934 6/25/2015
@dermoritz,我也是。”new MimetypesFileTypeMap().getContentType(path)“ 返回 ”application/octet-stream“,但 ”URLConnection.guessContentTypeFromName(path)“ 返回正确的 mime 类型。
10赞 Alex Fedulov 10/6/2015
这仅根据文件的扩展名进行检查。使用此方法无法检测到无效图像(没有图像内容和正确文件头的其他二进制文件)。
7赞 Biagio Cannistraro 2/18/2016
这是测试文件是否为图像的糟糕方法。更好的解决方案是:Files.probeContentType(path);
4赞 GameDroids 3/10/2012 #2

您可以尝试如下操作:

   import javax.activation.MimetypesFileTypeMap;

   File myFile;

   String mimeType = new MimetypesFileTypeMap().getContentType( myFile ));
   // mimeType should now be something like "image/png"

   if(mimeType.substring(0,5).equalsIgnoreCase("image")){
         // its an image
   }

这应该可以工作,尽管它似乎不是最优雅的版本。

18赞 prunge 3/10/2012 #3

在 Java 7 中,有 java.nio.file.Files.probeContentType() 方法。在 Windows 上,这使用文件扩展名和注册表(它不探测文件内容)。然后,您可以检查MIME类型的第二部分,并检查它是否采用 .<X>/image

评论

3赞 yngwietiger 5/20/2016
在 Linux 上,它似乎只查看我机器上的扩展程序。将.jpeg文件更改为 .txt,并返回“text/plain”。我喜欢下面 Krystian 的回答。
4赞 Stephen C 3/10/2012 #4

有多种方法可以做到这一点;查看其他答案和相关问题的链接。(Java 7 方法对我来说似乎最有吸引力,因为它默认使用特定于平台的约定,并且您可以提供自己的文件类型确定方案。

但是,我只想指出,没有任何机制是万无一失的:

  • 如果后缀不标准或错误,则依赖文件后缀的方法将被欺骗。

  • 如果文件具有不正确的内容类型属性或根本没有内容类型属性,则依赖于文件属性的方法(例如在文件系统中)将被欺骗。

  • 依赖于查看文件签名的方法可能会被恰好具有相同签名字节的二进制文件所欺骗。

  • 如果您不走运,即使只是简单地尝试将文件作为图像读取也可能被欺骗......取决于您尝试的图像格式。

36赞 Krystian 1/24/2014 #5
if( ImageIO.read(*here your input stream*) == null)
    *IS NOT IMAGE*    

还有一个答案:如何检查上传的文件是图像还是其他文件?

评论

1赞 zafar142003 1/22/2017
这是我能找到文件是否为图像文件的唯一方法(在装有 Java 8 的 Ubuntu 系统上)。
13赞 Biagio Cannistraro 2/18/2016 #6

您可以尝试如下操作:

String pathname="abc\xyz.png"
File file=new File(pathname);


String mimetype = Files.probeContentType(file.toPath());
//mimetype should be something like "image/png"

if (mimetype != null && mimetype.split("/")[0].equals("image")) {
    System.out.println("it is an image");
}
5赞 Ruslan Stelmachenko 9/22/2020 #7

其他答案建议将完整映像加载到内存 () 或使用标准 JDK 方法 ( 和 )。ImageIO.readMimetypesFileTypeMapFiles.probeContentType

如果不需要读取图像,则第一种方法效率不高,您真正想要的只是测试它是否是图像(并且可能保存它的内容类型,以便在将来读取此图像时将其设置为响应标头)。Content-Type

入站 JDK 方式通常只是测试文件扩展名,而不是真正为您提供可以信任的结果。

对我有用的方法是使用Apache Tika库。

private final Tika tika = new Tika();

private MimeType detectImageContentType(InputStream inputStream, String fileExtension) {
    Assert.notNull(inputStream, "InputStream must not be null");

    String fileName = fileExtension != null ? "image." + fileExtension : "image";
    MimeType detectedContentType = MimeType.valueOf(tika.detect(inputStream, fileName));
    log.trace("Detected image content type: {}", detectedContentType);

    if (!validMimeTypes.contains(detectedContentType)) {
        throw new InvalidImageContentTypeException(detectedContentType);
    }

    return detectedContentType;
}

类型检测基于给定文档流的内容和文档的名称。仅从流中读取有限数量的字节。

我只是作为 .没有它它也可以工作。但根据文档,在某些情况下,它有助于更好地检测。fileExtensionTika

  • 与此方法相比,此方法的主要优点是不会将完整文件读入内存 - 仅读取第一个字节。ImageIO.readTika

  • 与 JDK 相比,其主要优点是可以真正读取文件的第一个字节,而 JDK 在当前实现中只检查文件扩展名。MimetypesFileTypeMapFiles.probeContentTypeTika

顶级域名

  • 如果您打算对读取的图像执行某些操作(例如调整大小/裁剪/旋转它),请使用 Krystian 的答案ImageIO.read

  • 如果您只想检查(并可能存储)真实,请使用(此答案)。Content-TypeTika

  • 如果您在受信任的环境中工作,并且 100% 确定文件扩展名是正确的,请使用 from prunge's AnswerFiles.probeContentType

2赞 Bertie 9/25/2020 #8

这是我基于使用 tika 的答案的代码。

private static final Tika TIKA = new Tika();
public boolean isImageMimeType(File src) {
    try (FileInputStream fis = new FileInputStream(src)) {
        String mime = TIKA.detect(fis, src.getName());
        return mime.contains("/") 
                && mime.split("/")[0].equalsIgnoreCase("image");
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}