ByteArrayOutputStream 到 PrintWriter (Java Servlet)

发布于 2024-08-31 00:14:53 字数 311 浏览 10 评论 0原文

将 Servlet 中生成的 PDF (ByteArrayOutputStream) 写入 PrintWriter。

我正在拼命寻找一种将生成的 PDF 文件写入响应 PrintWriter 的方法。 由于层次结构链上的过滤器已经调用了response.getWriter(),我无法获取response.getOutputStream()。

我确实有一个 ByteArrayOutputStream,我在其中生成了 PDF。现在我需要的是一种将该 ByteArrayOutputStream 的内容输出到 PrintWriter 的方法。如果有人能给我帮助,我将不胜感激!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

只等公子 2024-09-07 00:14:54

你知道PrintWriter的编码是什么吗?如果是 Latin-1,您可以简单地将字节数组转换为 Latin-1 并写入 PrintWriter,

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

当然,这假设过滤器实际上没有写入任何内容。

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.

薄荷梦 2024-09-07 00:14:54

这是一个有点疯狂的想法,但我可能会这样解决。

如果您确实无法触及损坏的过滤器(真的吗?),请在损坏的过滤器之前编写另一个过滤器。

这看起来比实际情况更复杂,但这只是因为 Java 的冗长,所以请耐心等待。

基本上,它的作用是使用 HttpServletResponseWrapper 来包装/“覆盖”过滤器中的 response.getWriter() 以及链中跟随它的 servlet。

因此,当您损坏的 Filter 调用 response.getWriter() 时,它将获得一个代理 PrintWriter,该代理仅在第一次实际写入时调用真正的 response.getWriter()到。

然后,如果损坏的 Filter 调用 response.getWriter() 而不对其进行写入,就不再重要了。

我还没有实际测试过这段代码,但我相信它应该有效。

请注意,这假设损坏的 Filter 调用了 response.getWriter() 而没有实际写入任何内容。如果损坏的过滤器写入了一些内容,然后您又尝试向其中写入 PDF,那么输出无论如何都会损坏。

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

    }
}

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

    }
}
小姐丶请自重 2024-09-07 00:14:54

我收到如下错误:

此行下方没有任何内容错误 500:java.lang.IllegalStateException:SRVE0199E:OutputStream 已获得

通过设置解决:

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

现在输出变为:

此行下方没有任何内容

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

新雨望断虹 2024-09-07 00:14:53

如果其他东西已经调用了 getWriter,它很可能已经向响应写入了一些文本。此外,PrintWriter 用于文本 - 您想发送任意二进制数据...getOutputStream 绝对是方法向前,所以我会尝试找到调用 getWriter 的过滤器并修复它。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文