我在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;
}
答案 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) {}
}
,例如调整大小,改造或其他东西。
答案 1 :(得分:1)
我拥有的源代码(Java5,但我怀疑它已经发生了很大变化)表明,如果没有注册ImageInputStream服务提供程序,createImageInputStream
方法将返回null,从而获得该异常。
来自IIORegistry.getDefaultInstance()
使用的ImageIO
上的JavaDoc:
每个ThreadGroup都会收到自己的实例;这允许同一浏览器(例如)中的不同Applet各自拥有自己的注册表。
因此,它实际上可能是一个线程问题,因为你得到一个IIORegistry
的简单新实例。
编辑:深入挖掘源代码我发现了以下内容:
由于您传入了一个文件,因此很可能会获得FileImageInputStream
。但是,如果发生异常,服务提供商将返回null
。因此,可能会抛出FileNotFoundException
或任何其他IOException
,导致不创建流。
不幸的是,代码中没有记录,因此您必须以某种方式进行调试。这可能是由于缺少文件权限,文件损坏/不完整或文件丢失。
以下是FileImageInputStreamSpi#createInputStreamInstance()
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()方法在哪里?当存在异常时,流也必须关闭,以及代码块的正常终止。
症状听起来像是你的堆空间用完了或者某个时候。
这不是其他人指出的编码错误,因为问题是间歇性的。