朋友们,美好的一天!
首先,对不起我的英语。这是我的问题:
我是JSF(2.0)的新手,我正尝试使用BalusC算法从托管bean下载文件。功能正常运行,浏览器中出现“另存为…”对话框。但是我不知道如何在不重新加载/重定向视图的情况下返回文件下载错误消息(后备bean方法中的异常,DB错误等)。
我在视图上的隐藏按钮:
<h:form id="detailsDecisionMainForm"> <h:inputHidden id="docId" value="" /> <h:commandButton id="downloadAction" action="#{detailsDecisionGridBean.downloadForm()}" style="display: none;" /> </h:form>
我的托管bean(我可以使用哪个范围?我尝试过请求并查看范围)方法:
public String downloadForm() { log.fine("downloadForm call"); PdfService pdfService = new PdfServiceImpl(); ArmCommonService armCommonService = new ArmCommonServiceImpl(); String errorMessage = null; try { Long opUni = new Long(FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("detailsDecisionMainForm:docId")); log.fine("Document opUni = " + opUni); DocXML docXML = armCommonService.getDocXMLById(opUni); if (docXML != null) { File pdfFile = pdfService.getPdfReport(docXML.getXml(), docXML.getType()); if (pdfFile != null) { DownloadUtils.exportPdf(pdfFile); } else { log.log(Level.SEVERE, "downloadForm error: pdf generation error"); errorMessage = "PDF-document generation error."; } } else { log.log(Level.SEVERE, "downloadForm error: xml not found"); errorMessage = "XML-document not found."; } } catch (Exception ex) { log.log(Level.SEVERE, "downloadForm exception: " + ex.getMessage()); errorMessage = "File download exception."; } if (errorMessage != null) { FacesContext.getCurrentInstance().addMessage("detailsDecisionMainForm:downloadAction", new FacesMessage(errorMessage)); } return null; }
DownloadUtils.exportPdf()过程正确运行:
public static void exportPdf(File file) throws IOException { InputStream fileIS = null; try { log.fine("exportPdf call"); fileIS = new FileInputStream(file); FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext(); ec.responseReset(); ec.setResponseContentType(APPLICATION_PDF_UTF_8); byte[] buffer = ByteStreams.toByteArray(fileIS); ec.setResponseContentLength(buffer.length); ec.setResponseHeader(HttpHeaders.CONTENT_DISPOSITION, String.format(CONTENT_DISPOSITION_VALUE, new String(file.getName().getBytes(StandardCharsets.UTF_8)))); ec.getResponseOutputStream().write(buffer); fc.responseComplete(); } catch (Exception ex) { log.log(Level.SEVERE, "exportPdf exception: " + ex.getMessage()); } finally { if (fileIS != null) { fileIS.close(); log.fine("exportPdf inputstream file closed"); } } }
在downloadForm()错误/异常之后,如何防止视图重新呈现?以及如何显示带有消息文本的javascript alert()(将来-带有错误文本的jQuery.messager面板)?
谢谢!
为了防止重新加载整个页面,您必须通过ajax提交表单。但是,为了能够下载文件,您必须关闭ajax。一起做得不好。
最好的选择是将操作分为两个请求。首先发送一个ajax请求,该请求将在服务器端的临时位置创建文件。如果失败,则可以按常规方式显示人脸消息。成功后,您可以通过有条件呈现的JavaScript提交隐藏的非ajax命令按钮来自动触发第二个请求。然后,第二个请求可以将已经成功创建的文件从临时位置流式传输到响应。
之前已经提出并回答了类似的问题:有条件地提供文件下载或显示导出验证错误消息。但这涉及PrimeFaces和OmniFaces。以下是标准的JSF方法:
<h:form id="form"> ... <h:commandButton value="Export" action="#{bean.export}"> <f:ajax ... render="result" /> </h:commandButton> <h:panelGroup id="result"> <h:messages /> <h:commandButton id="download" action="#{bean.download}" style="display:none" /> <h:outputScript rendered="#{not facesContext.validationFailed}"> document.getElementById("form:download").onclick(); </h:outputScript> </h:panelGroup> </h:form>
并使用此@ViewScopedbean(逻辑基于您现有的逻辑)。基本上,只需File在导出操作(ajax)中获取as实例变量,然后在下载操作(非ajax)中将其流式传输即可。
@ViewScoped
File
private File pdfFile; public void export() { try { pdfFile = pdfService.getPdfReport(...); } catch (Exception e) { context.addMessage(...); } } public void download() throws IOException { DownloadUtils.exportPdf(pdfFile); }