java - 如何将生成的缓冲图像从 Servlet 传递到响应?

标签 java servlets web httpresponse bufferedimage

在我的 Servlet 中,我生成一个 BufferedImage:

BufferedImage bgImage = createImage();

我保存它:

saveImage(bgImg, getImageSaveDir() + IMAGE_NAME);

之后我想将其返回到响应以在浏览器中显示。

我尝试将图像发送到响应:

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 超时使请求超时。
  • 客户端的请求已终止。
  • 您发送了客户端无法理解的内容或 Not Acceptable MIME 类型,因此当网络服务器尝试提交响应时,出现错误。

对于 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)

所以,您可能想要:

关于java - 如何将生成的缓冲图像从 Servlet 传递到响应?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31291758/

相关文章:

java - 当您拆箱对象时,对象数据类型存储在哪里以便编译器可以执行转换?

java - 不支持的主要.次要版本 52.0

java - Tomcat-Servlet 不打印所有内容

javascript - 如何从 jQuery 的 $.ajax() 函数调用 servlet

java - 异常 : javax.net.ssl.SSLProtocolException 和编译器选项

JavaScript:访问在外部 .js 文件中定义的变量

java - 我如何在这里使用 "do while"命令?

java - 如何在 WebSphere Liberty 中设置间接 JNDI 查找?

javascript - 使用外部站点中存在的 javascript 闭包

javascript - 什么是内容下载 Chrome 调试工具?