31

我熟悉使用图像。我从 URL 检索/读取图像,其中 URL 没有文件扩展名。然后我希望将图像写入/保存到本地存储,但我必须指定图像文件扩展名(即 JPG、PNG 等),我无法通过 BufferedImage 检索其扩展名。

有人可以指出它是如何完成的吗?任何其他方法都可以。

4

4 回答 4

39

使用ImageReader.getFormatName()

您可以使用ImageIO.getImageReaders(Object input)获取文件的图像阅读器。

我自己没有测试过,但你可以试试这个:

ImageInputStream iis = ImageIO.createImageInputStream(file);

Iterator<ImageReader> imageReaders = ImageIO.getImageReaders(iis);

while (imageReaders.hasNext()) {
    ImageReader reader = (ImageReader) imageReaders.next();
    System.out.printf("formatName: %s%n", reader.getFormatName());
}
于 2012-07-12T07:38:55.900 回答
18

如果对象是 URL,则使用 ImageIO.createImageInputStream(obj) 的建议将不起作用。

一种替代方法是使用 URLConnection.guessContentTypeFromStream(InputStream stream) 方法。此方法通过检查流的前 12 个字节来猜测内容类型。

使用此方法的一个复杂之处在于,它需要将给定的流参数标记为支持,并且 java url.openStream() 返回的流不标记为支持。

此外,如果您想确定内容类型并将图像下载到 BufferedImage,那么最好解决方案只下载一次内容(而不是进行两次通过,一次确定内容类型,第二次下载图像)。

一种解决方案是使用 PushbackInputStream。PushbackInputStream 可用于下载第一个初始字节以确定内容类型。然后可以将字节推回流上,以便 ImageIO.read(stream) 可以完整地读取流。

可能的解决方案:

// URLConnection.guessContentTypeFromStream only needs the first 12 bytes, but
// just to be safe from future java api enhancements, we'll use a larger number
int pushbackLimit = 100;
InputStream urlStream = url.openStream();
PushbackInputStream pushUrlStream = new PushbackInputStream(urlStream, pushbackLimit);
byte [] firstBytes = new byte[pushbackLimit];
// download the first initial bytes into a byte array, which we will later pass to 
// URLConnection.guessContentTypeFromStream  
pushUrlStream.read(firstBytes);
// push the bytes back onto the PushbackInputStream so that the stream can be read 
// by ImageIO reader in its entirety
pushUrlStream.unread(firstBytes);

String imageType = null;
// Pass the initial bytes to URLConnection.guessContentTypeFromStream in the form of a
// ByteArrayInputStream, which is mark supported.
ByteArrayInputStream bais = new ByteArrayInputStream(firstBytes);
String mimeType = URLConnection.guessContentTypeFromStream(bais);
if (mimeType.startsWith("image/"))
    imageType = mimeType.substring("image/".length());
// else handle failure here

// read in image
BufferedImage inputImage = ImageIO.read(pushUrlStream);
于 2013-11-03T23:03:21.657 回答
5

如果您从 URL 获取图像,则意味着您可以通过InputStream. 从中您可以使用ImageIO获取图像类型(格式)并使用以下代码同时创建一个 BufferedImage。

public static BufferedImageWrapper getImageAndTypeFromInputStream(InputStream is) {

    String format = null;
    BufferedImage bufferedimage = null;
    try (ImageInputStream iis = ImageIO.createImageInputStream(is);) {

      Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);

      if (readers.hasNext()) {

        ImageReader reader = readers.next();
        format = reader.getFormatName();
        reader.setInput(iis);
        bufferedimage = reader.read(0);
      }
    } catch (IOException e) {
      logger.error("ERROR DETERMINING IMAGE TYPE!!!", e);
    }

    return new BufferedImageWrapper(format, bufferedimage);
  }

  public static class BufferedImageWrapper {

    private final String imageType;
    private final BufferedImage bufferedimage;

    /**
     * Constructor
     *
     * @param imageType
     * @param bufferedimage
     */
    public BufferedImageWrapper(String imageType, BufferedImage bufferedimage) {
      this.imageType = imageType;
      this.bufferedimage = bufferedimage;
    }

    public String getImageType() {

      return imageType;
    }

    public BufferedImage getBufferedimage() {

      return bufferedimage;
    }

  }
于 2016-04-21T13:23:18.180 回答
2

这通过输入 URL 对象(即图像)并返回文件扩展名来工作

但它需要初始下载到 java tmp 目录,然后在 ImageReader 尝试获取收集图像类型后将其删除

public String getImageFileExtFromUrl(URL urlObject) throws URISyntaxException, IOException{
    System.out.println("IN DOWNLOAD FILE FROM URL METHOD");
    String tmpFolder = System.getProperty("java.io.tmpdir");
    String tmpFileStr = tmpFolder + "/" + new Date().getTime();
    Files.copy(urlObject.openStream(), Paths.get(tmpFileStr), StandardCopyOption.REPLACE_EXISTING);
    File download = new File(tmpFileStr);
    System.out.println("FILE DOWNLOAD EXISTS: " + download.exists() );
    try{
        ImageInputStream iis = ImageIO.createImageInputStream(download);
        Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);

        ImageReader reader = iter.next();
        String formatName = reader.getFormatName();
        System.out.println("FOUND IMAGE FORMAT :" + formatName);
        iis.close();
        return formatName;
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        Files.delete(Paths.get(tmpFileStr));
    }
    return null;



}
于 2015-10-22T16:43:09.023 回答