我正在尝试将多个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
答案 0 :(得分:8)
如果您实际没有使用chunked encoding自己使用ChunkedOutputStream
使用例如{{}},那么您应 自行设置Transfer-Encoding: chunked
标题{3}}。只要响应缓冲区已满并且响应内容长度未知,Servlet API就会自动执行此操作。但是,无论何时在没有实际以chunked编码的方式写出正文的情况下自己设置此标头,行为都是完全未指定的,并且取决于所使用的servletcontainer。
删除该标头,让Servlet API完成其工作。为了提高性能(以便在响应缓冲区已满时Servlet API不会切换到分块编码),还要设置响应内容长度标头。
话虽如此,您的流媒体方法有点笨拙。无需按File
到URL
,并且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();