2009-11-06 5 views
9

보고서 내보내기 페이지에 대한 결과 페이지를 작성하고 싶습니다. 이 결과 페이지는 내보내기 상태를 표시하고이 내보내기의 다운로드를 제공해야합니다.로드시 backing bean 조치를 실행 하시겠습니까?

내보내기는 작업 방법으로 수행됩니다. 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 작업을 트리거하고 해당 요청이 파일 다운로드임을 알았습니다.

답변

15

또한 컴포넌트 시스템 이벤트, 특히 PreRenderViewEvent를 사용하여 JSF 2.0에서이를 해결할 수 있습니다.

렌더링하기 전에 다운로드 수신기를 시작하는 다운로드보기 (/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 메타 태그를 사용하여 스플래시 페이지로 리디렉션 할 수 있습니다.

+0

이 솔루션을 사용해보십시오. 페이지에 다른 컨트롤이없는 경우에만 작동합니다. 페이지에 드롭 다운 상자 선택과 같은 다른 컨트롤이 있고 페이지가 몇 번 앞뒤로왔다면'download()'가 계속 호출하고 값은 영원히 리셋됩니다. 따라서 그 실행을 영원히 한 번만 지켜줄 수있는 방법이 있습니까? – huahsin68

2

요청 당 하나의 응답 만 보낼 수 있습니다. 요청 당 두 개의 응답 (페이지 자체 및 다운로드 파일)을 보낼 수 없습니다. 가장 좋은 방법은 Javascript를 사용하여 페이지로드 후 (숨겨진) 양식을 제출하는 것입니다.

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

+1. 작동 할 것이지만, 이것을 언급하기 위해 a4j를 사용하고 싶습니다. (분명히 편집을 참조하십시오). – guerda

7

이전 답변은 양식을 제출하고 탐색을 변경합니다.

<rich:jsFunction action="#{bean.action}" name="loadFunction" /> 을 사용한 다음 window.onload = loadFunction;

관련 문제