jsf - 无法从 JSF 页面下载 zip 文件

标签 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浏览器,响应传输编码类型是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/

相关文章:

c# - 如果网站使用 SSL,我该如何使用 Webclient.DownloadFile 或 DownloadString?

node.js - apollo graphql 查询上传的文件

javascript - 模拟网页中的按钮单击

java - 如何使用 JSF 将文件上传到 glassfish

java - 在内存中的 zip 中解析 XML

C# .NET 为什么解压流时需要 Stream.Seek

java - 如何解压缩 zip 文件的特定目录中的所有文件?

ios - 如何使用 Alamofire 4 以字节为单位获取下载进度?

java - jsf inputtext 在 bean 中更改值后不更新值

java - session 过滤器的使用