如何从 Java 中的 URL 获取图像格式?

How can I fetch image format from a URL in Java?

我有一张从 url 中获取的图像,没有扩展名(jpg、gif、png 等)。

我下载图片没有问题。

BufferedImage image = null;
URL url = new URL(link);
image = ImageIO.read(url);

但是,我想在保存到磁盘之前知道文件的扩展名。我尝试了以下并且 ImageIO.createImageInputStream(image); 总是返回 null.

ImageInputStream iis = ImageIO.createImageInputStream(image);
//where image is BufferImage but it is always returning null.

while (imageReaders.hasNext()) {
    ImageReader reader = imageReaders.next();
    System.out.printf("formatName: %s%n", reader.getFormatName());

    return ImageFormatTypes.valueOf(reader.getFormatName());
}

如有任何建议,我们将不胜感激。

在 Java 7+ 中,您现在可以只使用 Files.probeContentType(path)

----------
public static String probeContentType(Path path)
                               throws IOException

Probes the content type of a file.

This method uses the installed FileTypeDetector implementations to probe the given file to determine its content type. Each file type detector's probeContentType is invoked, in turn, to probe the file type. If the file is recognized then the content type is returned. If the file is not recognized by any of the installed file type detectors then a system-default file type detector is invoked to guess the content type.

A given invocation of the Java virtual machine maintains a system-wide list of file type detectors. Installed file type detectors are loaded using the service-provider loading facility defined by the ServiceLoader class. Installed file type detectors are loaded using the system class loader. If the system class loader cannot be found then the extension class loader is used; If the extension class loader cannot be found then the bootstrap class loader is used. File type detectors are typically installed by placing them in a JAR file on the application class path or in the extension directory, the JAR file contains a provider-configuration file named java.nio.file.spi.FileTypeDetector in the resource directory META-INF/services, and the file lists one or more fully-qualified names of concrete subclass of FileTypeDetector that have a zero argument constructor. If the process of locating or instantiating the installed file type detectors fails then an unspecified error is thrown. The ordering that installed providers are located is implementation specific.

The return value of this method is the string form of the value of a Multipurpose Internet Mail Extension (MIME) content type as defined by RFC 2045: Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies. The string is guaranteed to be parsable according to the grammar in the RFC.

一旦创建 java.awt.Image,就没有格式了。它不是 PNG,也不是 JPEG,它只是一个 Java 图片。所以你不能从你的图像对象中获取图像格式。

您需要从 URL 获取它。最可靠的方法是检查 URL 的内容类型,然后从 ImageIO 提供程序获取扩展名:

URL url = new URL(link);
URLConnection conn = url.openConnection();
String contentType = conn.getContentType();

String suffix = null;
Iterator<ImageReader> readers =
    ImageIO.getImageReadersByMIMEType(contentType);
while (suffix == null && readers.hasNext()) {
    ImageReaderSpi provider = readers.next().getOriginatingProvider();
    if (provider != null) {
        String[] suffixes = provider.getFileSuffixes();
        if (suffixes != null) {
            suffix = suffixes[0];
        }
    }
}

您还可以将 URL 保存到一个临时文件中,这样您就可以在上面使用 Files.probeContentType:

URL url = new URL(link);
Path imageFile = Files.createTempFile("image", null);
try (InputStream stream = url.openStream()) {
    Files.copy(stream, imageFile, StandardCopyOption.REPLACE_EXISTING);
}

image = ImageIO.read(imageFile.toFile());
String contentType = Files.probeContentType(imageFile);
Files.delete(imageFile);

但是您仍然需要 ImageIO 提供程序来从 MIME 类型获得扩展。