Выполнять поддержку bean действия при загрузке?

Я хотел бы создать страницу результатов для страницы экспорта отчета. Эта страница результатов должна отображать статус экспорта и предлагать загрузку этого экспорта.

Экспорт выполняется в методе действий. Я могу выполнить его с помощью commandButton, но он должен выполняться автоматически при загрузке.

Как я могу это сделать?

JSF:

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

Поддержка bean:

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

Разъяснение: возможно ли это с a4j? Я думал о решении, которое Ajax-запрос запускает мое действие downloadReport, и его запрос - это загрузка файла.

Ответ 1

Вы также можете решить эту проблему в 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 для перенаправления на него на странице всплеска.

Ответ 2

Предыдущий ответ предоставит форму и, возможно, изменит навигацию.

Используйте <rich:jsFunction action="#{bean.action}" name="loadFunction" /> а затем window.onload = loadFunction;

Ответ 3

Вы можете отправить только один ответ на запрос. Вы не можете отправить два ответа (сама страница и файл загрузки) на запрос. Лучшее, что вы можете сделать, это использовать Javascript для отправки (скрытой) формы после загрузки страницы.

window.onload = function() {
    document.formname.submit();
}