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

現在輸出變爲:

沒有這條線