我正在尝试将多个 PDF 文件下载为一个 zip 文件,然后在 JSF 页面上更新详细信息 - 有效地表明我正在处理这些文件。我在幕后使用两个请求实现了这一点 - 1) 更新数据库详细信息并刷新屏幕 2) 下载 zip 文件。
这在单工作站 Windows 环境中运行良好,但当我在 Linux 环境中部署它时,在负载平衡器后面,我在尝试下载 zip 时出现空白页面。我已经编写了 SOP 统计信息来打印通过 JSF BB 发送到 ServletOutputStream 的文件的大小,我发现正在打印正确的文件大小。但不知何故,我一直在丢失 zip 以及更新的 JSF。这种情况在Windows中也随机出现,这让我很担心:(。请提供您宝贵的建议并帮助我解决这个问题。
您可能会考虑的一些要点: 我使用的是Richfaces 3.3.3 Final,IE 8浏览器,响应传输编码类型是chunked。
==== 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 监视器捕获的响应 header 。
(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
最佳答案
如果您实际上不使用chunked encoding 写出文件,您不应该自己设置Transfer-Encoding: chunked
header 。你自己使用例如 ChunkedOutputStream
.每当响应缓冲区已满且响应内容长度未知时,Servlet API 将自动执行此操作。但是,无论何时您自己设置此 header 而没有实际上以分块编码写出正文,行为是完全未指定的并且取决于所使用的 servletcontainer。
删除该 header 并让 Servlet API 完成其工作。为了提高性能(以便 Servlet API 在响应缓冲区已满时不会切换到分块编码),还要设置响应内容长度 header 。
话虽如此,您的流媒体方法有点笨拙。将 File
按摩到 URL
是不必要的,并且 for
循环中的 if-else
是不必要的。我可以向您提出以下建议吗?
// ...
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();
另见:
关于jsf - 无法从 JSF 页面下载 zip 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6950962/