javax.imageio.ImageIO创建ImageInputStream时出错

时间:2011-08-03 15:41:32

标签: java tomcat servlets inputstream javax.imageio

我在Tomcat 5.5中有一个Servlet,用于读取文件夹中的本地图像。然后将图像发送回Applet。

我得到这个“javax.imageio.IIOException:无法创建ImageInputStream!”错误,但不确定是什么导致它。

以前有人有这个问题吗?这可能是ImageIO中的线程问题吗?我不能重现这个问题,因为每1000次请求大约发生3次。

编辑:这是读取图像的Servlet代码。我只是在Servlet的doPost方法中以静态形式使用ImageIO.read(File),方法如下:

    doPost(req,resp){
       ...
        BufferedImage image = ImageIO.read(imageFile);
       ...
    }

以下是javax.imageio.ImageIO.read(File)的源代码:

    public static BufferedImage read(File input) throws IOException {
    if (input == null) {
        throw new IllegalArgumentException("input == null!");
    }
    if (!input.canRead()) {
        throw new IIOException("Can't read input file!");
    }

    ImageInputStream stream = createImageInputStream(input);
    if (stream == null) {
        throw new IIOException("Can't create an ImageInputStream!");
    }
    BufferedImage bi = read(stream);
    if (bi == null) {
        stream.close();
    }
    return bi;
    }

3 个答案:

答案 0 :(得分:2)

如果唯一的功能要求是从本地磁盘读取图像并使用servlet将其未修改返回到HTTP响应,那么您需要{{1完全没有。它只会增加不必要的开销和其他问题,就像你现在一样。

删除ImageIO内容,然后沿着一组正确的响应标头直接将原始映像从磁盘流式传输到HTTP响应。例如,

ImageIO

这就是全部。每当您想要在返回服务器内存中的图像之前操作图像时,您只需要String name = request.getParameter("name"); File file = new File("/path/to/images", name); response.setContentType(getServletContext().getMimeType(file.getName())); response.setHeader("Content-Length", String.valueOf(file.length())); response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\""); InputStream input = null; OutputStream output = null; try { input = new BufferedInputStream(new FileInputStream(file)); output = new BufferedOutputStream(response.getOutputStream()); byte[] buffer = new byte[8192]; for (int length; (length = input.read(buffer)) > 0;) { output.write(buffer, 0, length); } } finally { if (output != null) try { output.close(); } catch (IOException logOrIgnore) {} if (input != null) try { input.close(); } catch (IOException logOrIgnore) {} } ,例如调整大小,改造或其他东西。

可以找到另一个更强大的此类servlet示例here和更高级的here

答案 1 :(得分:1)

我拥有的源代码(Java5,但我怀疑它已经发生了很大变化)表明,如果没有注册ImageInputStream服务提供程序,createImageInputStream方法将返回null,从而获得该异常。

来自IIORegistry.getDefaultInstance()使用的ImageIO上的JavaDoc:

  

每个ThreadGroup都会收到自己的实例;这允许同一浏览器(例如)中的不同Applet各自拥有自己的注册表。

因此,它实际上可能是一个线程问题,因为你得到一个IIORegistry的简单新实例。

编辑:深入挖掘源代码我发现了以下内容:

由于您传入了一个文件,因此很可能会获得FileImageInputStream。但是,如果发生异常,服务提供商将返回null。因此,可能会抛出FileNotFoundException或任何其他IOException,导致不创建流。

不幸的是,代码中没有记录,因此您必须以某种方式进行调试。这可能是由于缺少文件权限,文件损坏/不完整或文件丢失。

以下是FileImageInputStreamSpi#createInputStreamInstance()

的Java5源代码
public ImageInputStream createInputStreamInstance(Object input,
                                                  boolean useCache,
                                                  File cacheDir) {
    if (input instanceof File) {
        try {
            return new FileImageInputStream((File)input);
        } catch (Exception e) {
            return null;
        }
    } else {
        throw new IllegalArgumentException();
    }
}

答案 2 :(得分:0)

您在异常处理中使用close()方法在哪里?当存在异常时,流也必须关闭,以及代码块的正常终止。

症状听起来像是你的堆空间用完了或者某个时候。

这不是其他人指出的编码错误,因为问题是间歇性的。