无法从JSF页面下载zip文件

时间:2011-08-05 03:06:59

标签: jsf zip download load-balancing

我正在尝试将多个PDF文件作为一个zip文件下载,然后更新JSF页面上的详细信息 - 有效地显示我正在处理这些文件。我使用场景后面的两个请求实现了这一点 - 1)更新数据库详细信息并刷新屏幕2)下载zip文件。

这在单工作站Windows环境中运行良好,但是当我在Linux环境中部署它时,在负载均衡器后面,我在尝试下载zip时得到一个空白页面。我已经编写了SOP统计信息来打印通过JSF BB发送到ServletOutputStream的文件的大小,我发现正在打印正确的文件大小。但不知何故,我一直在丢失zip以及更新的JSF。这种情况也会在Windows中随机出现,这让我很担心:(。请提供宝贵的建议并帮助我摆脱这个问题。

您可能会考虑考虑以下几点: 我正在使用Richfaces 3.3.3 Final,IE 8浏览器,响应传输编码类型被分块。

==== BB方法如下:

String checkoutDoc = service.checkout(docId,true,contract, error);
FacesContext ctx = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) ctx.getExternalContext().getResponse();
File tempPdf = new File(checkoutDoc);URI tempURI = tempPdf.toURI();
URL pdfURL = tempURI.toURL();ServletOutputStream outstream =response.getOutputStream();
try 
{
 URLConnection urlConn = pdfURL.openConnection();
 response.setContentType("application/zip");
 response.setHeader("Transfer-Encoding", "chunked");
 response.addHeader("Content-disposition", "attachment;filename="+docId.toString()+".zip" );
 BufferedInputStream bufInStrm = new BufferedInputStream (urlConn.getInputStream());
 int readBytes = 0;
 int bufferSize = 8192;
 byte[] buffer = new byte[bufferSize];
 while ((readBytes = bufInStrm.read(buffer)) != -1){
if (readBytes == bufferSize) {
    outstream.write(buffer);
 }else{
    outstream.write(buffer, 0, readBytes);
    }
    outstream.flush();
    response.flushBuffer();
    }
    bufInStrm.close();
    }finally{
     outstream.close();
    }
    FacesContext.getCurrentInstance().responseComplete();
}

我使用Firefox Http监视器捕获的响应标头如下所示。

(Request-Line)  POST /XXX/application/pages/xxx.xhtml HTTP/1.1
Host    xxx.xxx.com
User-Agent  Mozilla/5.0 (Windows NT 5.1; rv:5.0.1) Gecko/20100101 Firefox/5.0.1
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection  keep-alive
Referer http://xxx.com/xxx/application/pages/xxx.xhtml
Cookie  JSESSIONID=E27C156AA37E5984073FAB847E4958D2.XXXX;  fontSize=null; pageWidth=fullWidth
Content-Type    multipart/form-data; boundary=---------------------------288695814700
Content-Length  1442

1 个答案:

答案 0 :(得分:8)

如果您实际没有使用chunked encoding自己使用ChunkedOutputStream使用例如{{}},那么您应 自行设置Transfer-Encoding: chunked标题{3}}。只要响应缓冲区已满并且响应内容长度未知,Servlet API就会自动执行此操作。但是,无论何时在没有实际以chunked编码的方式写出正文的情况下自己设置此标头,行为都是完全未指定的,并且取决于所使用的servletcontainer。

删除该标头,让Servlet API完成其工作。为了提高性能(以便在响应缓冲区已满时Servlet API不会切换到分块编码),还要设置响应内容长度标头。

话虽如此,您的流媒体方法有点笨拙。无需按FileURL,并且if-else循环中的for是不必要的。我可以建议你以下吗?

// ...
File tempPdf = new File(checkoutDoc);

ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
externalContext.setResponseContentType("application/zip");
externalContext.setResponseHeader("Content-Disposition", "attachment;filename=\"" + docId + ".zip\"");
externalContext.setResponseHeader("Content-Length", String.valueOf(tempPdf.length()));

Files.copy(tempPdf.toPath(), externalContext.getResponseOutputStream());
FacesContext.getCurrentInstance().responseComplete();

另见: