JSF /煤层。我有一个页面接受用户通过表单提供的一些参数,然后(当用户点击页面上的按钮时)服务器生成一个文件并将其发送到响应中,以便提示用户保存 - 作为对话。
以下是我遇到问题的情况:
最初,我尝试了一些黑客强制重新发布<h:messages/>
标签,但没有什么是令人满意的。 我现在怀疑根本原因是因为当我在响应中放置文件时Seam没有进入渲染响应阶段。
这是我的按钮:
<h:commandButton value="#{messages.Reports_RunReportPDF}"
action="#{bean.generateReportPdf}"/>
这是我的行动处理程序:
public String generateReportPdf() throws IOException {
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse();
ServletOutputStream servletOutputStream = response.getOutputStream();
// add this header to make browser prompt user with a save-as dialog
response.addHeader("Content-Disposition",
"attachment;filename=" + reportName + ".pdf");
response.setContentType(exportType.contentType());
try {
HashMap<String, Object> parameters = getReportParameters();
ReportContent content = createReport(parameters);
servletOutputStream.write(content.getContents());
servletOutputStream.flush();
servletOutputStream.close();
} catch (ReportingException e) {
e.printStackTrace();
return "fail";
}
return "success";
}
如果我注释掉添加文件的代码(并且只返回"success"
),该页面将遵循我已正确设置的导航规则。但是对于该文件,页面保持完全相同按下按钮之前。
那么,我如何在响应中返回一个文件,并导致<h:messages/>
标记被重新呈现?
答案 0 :(得分:0)
在写完
后将其添加到您的方法中//Skip the rest of JSF phases
FacesContext.getCurrentInstance().responseComplete();
您可能还希望在finally块中添加close,以便确保在发生异常时正确关闭流。 或者从Lombok添加@Cleanup注释,它会自动为您执行
<强>更新强>
如果您在长时间对话中,可以在重定向之前结束对话,从而删除验证消息。
@End(beforeRedirect=true)
答案 1 :(得分:0)
那么,我怎样才能在响应中返回一个文件,并导致标记被重新呈现?
单个HTTP请求无法实现。每个请求只能返回一个响应。这不是JSF限制,这是HTTP限制。
你can使用JavaScript只需点击一下即可触发两个HTTP请求,但在你的特定情况下,由于JSF对消息的请求取决于PDF下载请求的结果,因此无法正常工作。我没有看到其他方法,除了让servlet设置一个会话范围的托管属性,表示PDF导出的状态,并引入一个ajax轮询,它会间隔地请求此属性,并在它不再为null时停止。