Dylan
Dylan

Reputation: 955

How to pass the generated Buffered image from Servlet to the response?

In my Servlet I generate a BufferedImage:

BufferedImage bgImage = createImage();

and I save it:

saveImage(bgImg, getImageSaveDir() + IMAGE_NAME);

After that I want to return it to the response to show in a browser.

I tried to send the image to the response:

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();
}

But I receive an Exception:

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?

I've tried this:

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();

Now the Exception does not appear, but the code still doesn't work:(

Upvotes: 1

Views: 2916

Answers (1)

hagrawal7777
hagrawal7777

Reputation: 14658

See the below code of org.apache.catalina.connector.OutputBuffer.realWriteBytes which is where the exception is coming.

    // 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);
        }
    }

Now notice the comment in the exception which says

An IOException on a write is almost always due to the remote client aborting the request.

To me, it looks like some connection problem between your browser and server. Probably the connection is broken.

Now there could be multiple reasons for HTTP connection getting disconnected, like:

  • Request was taking too long to respond, so the web server timed out the request, as per the HTTP timeout.
  • Request was terminated from client.
  • You sent something which was not understood by client or non-acceptable MIME type, so while web server was trying to commit the response, there was error.

In case of Weblogic, if I initiate a server transaction from browser, and then close the browser before server could respond, then while commiting the response, WL will throw below exception.
In your case as well root exception is IOException but it is wrapped to ClientAbortException to be meaningful on log console.

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)

So, you may want to:

Upvotes: 1

Related Questions