如何将生成的缓冲图像从 Servlet 传递到响应?
How to pass the generated Buffered image from Servlet to the response?
在我的 Servlet 中,我生成了一个 BufferedImage:
BufferedImage bgImage = createImage();
然后保存:
saveImage(bgImg, getImageSaveDir() + IMAGE_NAME);
之后我想 return 将其响应显示在浏览器中。
我尝试将图像发送到响应:
File imageFile = new File(getImageSaveDir() + IMAGE_NAME);
response.setContentType("image/png");
BufferedImage bufferedImg = ImageIO.read(imageFile);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bufferedImg, "png", out);
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
但是我收到一个异常:
ClientAbortException: java.net.SocketException: Broken pipe
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:369)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:448)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:318)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:296)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:98)
at javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at javax.imageio.ImageIO.write(ImageIO.java:1580)
at tv.clever.xml.TeamImageProcessor.process(TeamImageProcessor.java:157)
at tv.clever.api.ApiServlet.doProcessing(ApiServlet.java:458)
at tv.clever.api.ApiServlet.process(ApiServlet.java:219)
at tv.clever.api.ApiServlet.doPost(ApiServlet.java:98)
at tv.clever.api.ApiServlet.doGet(ApiServlet.java:86)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.messageresource.UTF8EncodingFilter.doFilter(UTF8EncodingFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.security.URLFilter.doFilter(URLFilter.java:50)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.security.CrossScriptingFilter.doFilter(CrossScriptingFilter.java:38)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:761)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:448)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:363)
at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:785)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:124)
at org.apache.coyote.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:598)
at org.apache.coyote.Response.doWrite(Response.java:533)
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:364)
... 39 more
What is the best way to pass the generated Buffered image from Servlet to the response and display it in the browser?
我试过这个:
BufferedImage originalImage = ImageIO.read(new File(getImageSaveDir() + IMAGE_NAME));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "png", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
response.setContentType("image/png");
response.setContentLength(imageInByte.length);
ServletOutputStream servletoutputstream = response.getOutputStream();
servletoutputstream.write(imageInByte);
servletoutputstream.flush();
现在异常没有出现,但是代码还是不行:(
请参阅下面的 org.apache.catalina.connector.OutputBuffer.realWriteBytes
代码,这是出现异常的地方。
// If we really have something to write
if (cnt > 0) {
// real write to the adapter
outputChunk.setBytes(buf, off, cnt);
try {
coyoteResponse.doWrite(outputChunk);
} catch (IOException e) {
// An IOException on a write is almost always due to
// the remote client aborting the request. Wrap this
// so that it can be handled better by the error dispatcher.
throw new ClientAbortException(e);
}
}
现在请注意异常中的注释
An IOException on a write is almost always due to the remote client
aborting the request.
在我看来,您的浏览器和服务器之间似乎存在连接问题。可能连接断开了。
现在可能有多种原因导致 HTTP 连接断开,例如:
- 请求响应时间过长,因此网络服务器根据 HTTP 超时使请求超时。
- 来自客户端的请求被终止。
- 您发送了客户端无法理解的内容或不可接受的 MIME 类型,因此当 Web 服务器尝试提交响应时出现错误。
在 Weblogic 的情况下,如果我从浏览器启动服务器事务,然后在服务器响应之前关闭浏览器,那么在提交响应时,WL 将抛出以下异常。
在您的情况下,根异常也是 IOException
但它被包装到 ClientAbortException
以便在日志控制台上有意义。
java.io.IOException: An established connection was aborted by the software in your host machine
at sun.nio.ch.SocketDispatcher.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:487)
因此,您可能想要:
- 从连接角度调试。可能有 Fiddler 用于调试 HTTP 流量。
- 确认服务器没有花费太长时间,因此 Web 服务器正在获取 HTTP 超时。如果是这样,请增加 Web 服务器 HTTP 超时限制。
- 验证图像类型是 "png"。
- 尝试不同的方式将图像发送到 UI - https://www.google.ca/search?q=setContentType&ie=utf-8&oe=utf-8&gws_rd=cr&ei=RBydVZLxNsLp-QHivoP4Bg#q=servlet+send+image+in+response
- 您绝对应该尝试的一种方法是读取或转换字节数组中的图像,然后使用
ServletOutputStream#write()
直接将其提交给客户端
在我的 Servlet 中,我生成了一个 BufferedImage:
BufferedImage bgImage = createImage();
然后保存:
saveImage(bgImg, getImageSaveDir() + IMAGE_NAME);
之后我想 return 将其响应显示在浏览器中。
我尝试将图像发送到响应:
File imageFile = new File(getImageSaveDir() + IMAGE_NAME);
response.setContentType("image/png");
BufferedImage bufferedImg = ImageIO.read(imageFile);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bufferedImg, "png", out);
out.close();
} catch (Exception ex) {
ex.printStackTrace();
}
但是我收到一个异常:
ClientAbortException: java.net.SocketException: Broken pipe
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:369)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:448)
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:318)
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:296)
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:98)
at javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at javax.imageio.ImageIO.write(ImageIO.java:1580)
at tv.clever.xml.TeamImageProcessor.process(TeamImageProcessor.java:157)
at tv.clever.api.ApiServlet.doProcessing(ApiServlet.java:458)
at tv.clever.api.ApiServlet.process(ApiServlet.java:219)
at tv.clever.api.ApiServlet.doPost(ApiServlet.java:98)
at tv.clever.api.ApiServlet.doGet(ApiServlet.java:86)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:723)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.messageresource.UTF8EncodingFilter.doFilter(UTF8EncodingFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.security.URLFilter.doFilter(URLFilter.java:50)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at tv.clever.utils.security.CrossScriptingFilter.doFilter(CrossScriptingFilter.java:38)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:470)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at org.apache.coyote.http11.InternalOutputBuffer.realWriteBytes(InternalOutputBuffer.java:761)
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:448)
at org.apache.tomcat.util.buf.ByteChunk.append(ByteChunk.java:363)
at org.apache.coyote.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:785)
at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:124)
at org.apache.coyote.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:598)
at org.apache.coyote.Response.doWrite(Response.java:533)
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:364)
... 39 more
What is the best way to pass the generated Buffered image from Servlet to the response and display it in the browser?
我试过这个:
BufferedImage originalImage = ImageIO.read(new File(getImageSaveDir() + IMAGE_NAME));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(originalImage, "png", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray();
baos.close();
response.setContentType("image/png");
response.setContentLength(imageInByte.length);
ServletOutputStream servletoutputstream = response.getOutputStream();
servletoutputstream.write(imageInByte);
servletoutputstream.flush();
现在异常没有出现,但是代码还是不行:(
请参阅下面的 org.apache.catalina.connector.OutputBuffer.realWriteBytes
代码,这是出现异常的地方。
// If we really have something to write
if (cnt > 0) {
// real write to the adapter
outputChunk.setBytes(buf, off, cnt);
try {
coyoteResponse.doWrite(outputChunk);
} catch (IOException e) {
// An IOException on a write is almost always due to
// the remote client aborting the request. Wrap this
// so that it can be handled better by the error dispatcher.
throw new ClientAbortException(e);
}
}
现在请注意异常中的注释
An IOException on a write is almost always due to the remote client aborting the request.
在我看来,您的浏览器和服务器之间似乎存在连接问题。可能连接断开了。
现在可能有多种原因导致 HTTP 连接断开,例如:
- 请求响应时间过长,因此网络服务器根据 HTTP 超时使请求超时。
- 来自客户端的请求被终止。
- 您发送了客户端无法理解的内容或不可接受的 MIME 类型,因此当 Web 服务器尝试提交响应时出现错误。
在 Weblogic 的情况下,如果我从浏览器启动服务器事务,然后在服务器响应之前关闭浏览器,那么在提交响应时,WL 将抛出以下异常。
在您的情况下,根异常也是 IOException
但它被包装到 ClientAbortException
以便在日志控制台上有意义。
java.io.IOException: An established connection was aborted by the software in your host machine
at sun.nio.ch.SocketDispatcher.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:487)
因此,您可能想要:
- 从连接角度调试。可能有 Fiddler 用于调试 HTTP 流量。
- 确认服务器没有花费太长时间,因此 Web 服务器正在获取 HTTP 超时。如果是这样,请增加 Web 服务器 HTTP 超时限制。
- 验证图像类型是 "png"。
- 尝试不同的方式将图像发送到 UI - https://www.google.ca/search?q=setContentType&ie=utf-8&oe=utf-8&gws_rd=cr&ei=RBydVZLxNsLp-QHivoP4Bg#q=servlet+send+image+in+response
- 您绝对应该尝试的一种方法是读取或转换字节数组中的图像,然后使用
ServletOutputStream#write()
直接将其提交给客户端
- 您绝对应该尝试的一种方法是读取或转换字节数组中的图像,然后使用