我正在尝试使用OmniFaces <p:ajaxstatus />
函数下载文件时创建Faces.sendFile
之类的指标。当用户单击“导出”链接时,会出现一个对话框,告诉他们正在创建文件(因为这可能需要一些时间,具体取决于数据大小),然后在文件下载后,消息将关闭。
在我的xhtml中:
<p:dialog widgetVar="excelDialog" modal="true">
<h2>Building Spreadsheet</h2>
</p:dialog>
<h:commandLink value="Export" action="#{resultsBean.excelExport}" onclick="excelDialog.show();" />
并在我的ViewScoped bean中:
public void excelExport() throws IOException {
ExcelExport ee = new ExcelExport(results);
Faces.sendFile(ee.getFile(), true);
}
我无法想象的是如何在响应完成后关闭对话框。
我尝试过使用PrimeFaces RequestContext(适用于非ajax请求),但不起作用。我想知道这是否是因为Faces.sendFile
在使用RequestContext之前调用FacesContext.responseComplete()
。
public void excelExport() throws IOException {
ExcelExport ee = new ExcelExport(results);
Faces.sendFile(ee.getFile(), true);
RequestContext c = RequestContext.getCurrentInstance();
c.execute("PF('excelDialog').hide();");
}
答案 0 :(得分:4)
我想知道这是因为
Faces.sendFile
在使用RequestContext之前调用FacesContext.responseComplete()
。
它只是防止下载文件内容被破坏,因为其他东西试图将更多数据写入响应。
您基本上是在尝试针对单个请求发送多个回复。这是不可能的。每个请求只能发送一个响应。如果您的尝试成功,下载文件内容将被破坏,因为代表PrimeFaces ajax响应的某些XML代码将附加到下载文件内容的末尾。
您基本上需要发送2个请求,从而在第一个请求结束时自动触发第二个请求。第一个请求应该准备文件并将其停放在某处(@ViewScoped
bean的属性?)然后关闭对话框并触发第二个请求。第二个请求应该只下载停放的文件。第一个请求可以像ajax一样完成<p:commandButton>
,但第二个请求必须完全同步,原因很明显。您可以使用使用CSS隐藏的<h:commandLink>
执行第二个请求。
E.g。
<h:form id="formId">
<p:commandLink value="Export" action="#{resultsBean.excelExport}"
onclick="excelDialog.show();"
oncomplete="excelDialog.hide(); document.getElementById('formId:linkId').click();" />
<h:commandLink id="linkId" action="#{resultsBean.excelDownload}" style="display:none;" />
</h:form>
与
private File excelFile;
public void excelExport() {
excelFile= new ExcelExport(results).getFile();
}
public void excelDownload() throws IOException {
Faces.sendFile(excelFile, true);
}