3

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

我拼命寻找一种方法将生成的PDF文件写入到PrintWriter响应中。 由于Filter up层次结构链已经调用了response.getWriter(),我无法获得response.getOutputStream()。

我确实有一个ByteArrayOutputStream,我在其中生成PDF。现在我需要的是将此ByteArrayOutputStream的内容输出到PrintWriter的方法。如果有人能给我一个援助之手,将非常感谢!

+0

下面那是什么过滤器做什么? – BalusC 2010-04-26 11:55:49

+0

我不知道 - 在我轮到之前有几个过滤器会被调用。没有办法触及这些:( – Thomas 2010-04-26 12:18:32

+1

如果过滤器写了任何东西,你的输出将会损坏,如果过滤器没有写入任何东西,它不应该叫做response.getWriter()。 – 2010-04-26 13:22:23

回答

7

如果其他东西已经叫做getWriter,那么它可能已经写了一些文本给响应。此外,PrintWriter文本 - 你要发送任意的二进制数据 ... getOutputStream绝对是前进的方向,所以我会尝试寻找一种呼吁getWriter过滤器和修复来代替。

+0

同意 - 其他任何东西(试图强制通过'PrintWriter'发送二进制数据)必然会成为一个丑陋的黑客。 – Jesper 2010-04-26 11:48:16

+0

嗯,我看到感谢您的帮助 - 它接近一个不好的情况,因为我不能在之前触摸过滤器...任何建议在一个丑陋的黑客? – Thomas 2010-04-26 12:19:44

+0

@Thomas:不是真的......通过PrintWriter推送二进制数据就像是在圆孔中放置一个方形钉。为什么你不能更换过滤器?他们真的没有什么可以做的吗? – 2010-04-26 12:49:19

0

你知道PrintWriter的编码是什么吗?如果是拉丁文-1,可以字节数组简单地转换到Latin-1的和写的PrintWriter,

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

。当然,这是假设过滤器并没有真正写什么。

+1

不正确,他应该使用response.getOutputStream()。 – 2010-04-26 12:03:50

+0

@Christoffer:只修正它会抛出一个异常,因为事先已经调用了response.getWriter()。 – Thomas 2010-04-26 12:22:03

+0

@Thomas:问题就成为了为什么某些东西叫做getWriter()而没有写任何东西。这是没有道理的,至少听起来像是一个等待发生的错误。 – 2010-04-26 13:20:37

0

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

如果您确实无法触摸破碎的滤镜(真的?),请在破碎的滤镜之前再写一个滤镜。

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

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

所以,当你的破碎过滤器调用response.getWriter()时,它将代替获得一个代理PrintWriter,它在第一次实际写入时只调用实际的response.getWriter()

然后它不再重要,如果破碎的过滤器调用response.getWriter()而不写入它。

我没有真正测试过这段代码,但我相信它应该可以工作。

请注意,这假定破碎的过滤器在没有实际写入内容的情况下调用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; 
     } 

    } 
} 
-1

我得到错误,如:

没有这个lineError 500以下:java.lang中。IllegalStateException异常:SRVE0199E:OutputStream中已经取得

解决设置:

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

现在输出变为:

没有这条线