简体   繁体   中英

ByteArrayOutputStream to PrintWriter (Java Servlet)

Writing generated PDF (ByteArrayOutputStream) in a Servlet to PrintWriter.

I am desperately looking for a way to write a generated PDF file to the response PrintWriter. Since a Filter up the hierarchy chain has already called response.getWriter() I can't get response.getOutputStream().

I do have a ByteArrayOutputStream where I generated the PDF into. Now all I need is a way to output the content of this ByteArrayOutputStream to the PrintWriter. If anyone could give me a helping hand would be very much appreciated!

If something else has already called getWriter , it may well have already written some text to the response. Besides, PrintWriter is for text - you want to send arbitrary binary data... getOutputStream is definitely the way forward, so I would try to find the filter which has called getWriter and fix that instead.

Do you know what's the encoding of PrintWriter? If it's Latin-1, you can simply convert the byte array to Latin-1 and write to the PrintWriter,

   String latin1 = byteStream.toString("ISO-8859-1");
   response.getWriter().write(latin1);

Of course, this assumes the filter doesn't really write anything.

Here's a somewhat crazy idea, but i would probably solve it like this.

If you really can't touch the broken Filter ( really? ), write another filter that you place before the broken Filter.

This looks more complex than it is, but that's only because of Java's verbosity, so please bear with me.

Basically what it does is that it uses HttpServletResponseWrapper to wrap/"override" response.getWriter() in filters and the servlet following it in the chain.

So when your broken Filter calls response.getWriter() , it will instead get a proxy PrintWriter that only calls the real response.getWriter() the first time it is actually written to.

Then it no longer matters if the broken Filter calls response.getWriter() without writing to it.

I haven't actually tested this code, but i believe it should work.

Note that this assumes that the broken Filter calls response.getWriter() without actually writing something. The output would be corrupt anyway if the broken filter wrote something and then you tried to write a PDF to it as well.

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;

public class BrokenWriterGetterFixingFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, final ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        filterChain.doFilter(servletRequest, new BrokenWriterGetterFixingResponseWrapper((HttpServletResponse) servletResponse));
    }

    @Override
    public void destroy() {
    }

    private static class BrokenWriterGetterFixingResponseWrapper extends HttpServletResponseWrapper {
        public BrokenWriterGetterFixingResponseWrapper(HttpServletResponse response) {
            super(response);
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return new PrintWriter(new BrokenWriterGetterFixingWriter(getResponse()));
        }
    }

    private static class BrokenWriterGetterFixingWriter extends Writer {
        private PrintWriter responseWriter;
        private final ServletResponse response;

        public BrokenWriterGetterFixingWriter(ServletResponse response) {
            this.response = response;
        }

        @Override
        public void write(char[] cbuf, int off, int len) throws IOException {
            getResponseWriter().write(cbuf, off, len);
        }

        @Override
        public void flush() throws IOException {
            getResponseWriter().flush();
        }

        @Override
        public void close() throws IOException {
            getResponseWriter().close();
        }

        private PrintWriter getResponseWriter() throws IOException {
            if (null == responseWriter) {
                responseWriter = response.getWriter();
            }
            return responseWriter;
        }

    }
}

I was getting error like:

nothing below this lineError 500: java.lang.IllegalStateException: SRVE0199E: OutputStream already obtained

Solved by setting:

response.getOutputStream().write(bytes);
response.setContentLength(bytes.length);

Now output becomes:

nothing below this line

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM