10

我想为报告导出页面构建一个结果页面。此结果页面必须显示导出状态并提供此导出的下载。

导出是在操作方法中完成的。我可以通过 a 执行它,commandButton但它必须在加载时自动执行。

我怎样才能做到这一点?

JSF:

<h:commandButton value="Download report" action="#{resultsView.downloadReport}"/>

支持豆:

  public String downloadReport() {
    ...
    FileDownloadUtil.downloadContent(tmpReport, REPORT_FILENAME);
    // Stay on this page
    return null;
  }

澄清:这对a4j可行吗?我想到了一个 Ajax 请求触发我的downloadReport操作的解决方案,它的请求是文件下载。

4

4 回答 4

15

您还可以在 JSF 2.0 中使用组件系统事件(特别是 PreRenderViewEvent)来解决这个问题。

只需创建一个下载视图 (/download.xhtml),它会在渲染之前触发下载侦听器。

<?xml version="1.0" encoding="UTF-8"?>
<f:view
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core">
    <f:event type="preRenderView" listener="#{reportBean.download}"/>
</f:view>

然后,在您的报告 bean(使用 JSR-299 定义)中,您推送文件并将响应标记为完成。

public @Named @RequestScoped class ReportBean {

   public void download() throws Exception {
      FacesContext ctx = FacesContext.getCurrentInstance();
      pushFile(
           ctx.getExternalContext(),
           "/path/to/a/pdf/file.pdf",
           "file.pdf"
      ); 
      ctx.responseComplete();
   }

   private void pushFile(ExternalContext extCtx,
         String fileName, String displayName) throws IOException {
      File f = new File(fileName);
      int length = 0; 
      OutputStream os = extCtx.getResponseOutputStream();
      String mimetype = extCtx.getMimeType(fileName);

      extCtx.setResponseContentType(
         (mimetype != null) ? mimetype : "application/octet-stream");
      extCtx.setResponseContentLength((int) f.length());
      extCtx.setResponseHeader("Content-Disposition",
         "attachment; filename=\"" + displayName + "\"");

      // Stream to the requester.
      byte[] bbuf = new byte[1024];
      DataInputStream in = new DataInputStream(new FileInputStream(f));

      while ((in != null) && ((length = in.read(bbuf)) != -1)) {
         os.write(bbuf, 0, length);
      }  

      in.close();
   }
}

这里的所有都是它的!

您可以链接到下载页面 (/download.jsf),也可以使用 HTML 元标记在启动页面上重定向到它。

于 2009-11-10T19:07:45.443 回答
8

上一个答案将提交表单并可能更改导航。

<rich:jsFunction action="#{bean.action}" name="loadFunction" /> 然后使用window.onload = loadFunction;

于 2009-11-08T09:05:26.770 回答
3

每个请求只能发送一个响应。您不能为每个请求发送两个响应(页面本身和下载文件)。您可以做的最好的事情是在页面加载后使用 Javascript 提交(隐藏)表单。

window.onload = function() {
    document.formname.submit();
}
于 2009-11-06T11:11:37.103 回答
0

使用事件

<ui:composition 
            xmlns="http://www.w3.org/1999/xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:f="http://xmlns.jcp.org/jsf/core"
>
   <f:event type="preRenderView" listener="#{beanName.method}"/>
   ...    
</ui:composition>
于 2018-06-09T16:18:43.147 回答