2011-10-19 5 views
16

JDK 1.6, JSF 2.1, PrimeFaces 2.2.1, POI 3.2, 아파치 톰캣 사용 7엑셀 JSF로 내보내기 및 PrimeFaces

나는 기반으로 엑셀 파일의 다운로드를 허용하도록 설정에 서블릿을 시도하고있다 사용자 선택. 엑셀 문서는 런타임에 생성됩니다.

오류가 없으며 코드가 서블릿에 들어갑니다.

버튼을 클릭해도 아무런 변화가 없습니다. Excel 문서의 데이터에서 순서 및 사용자 지정 서식을 사용해야하므로 PrimeFaces에서 사용하는 데이터 테이블 내보내기를 사용하지 않습니다.

ExportExcelReports.java

protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
     throws ServletException, IOException {  
    response.setContentType("application/vnd.ms-excel"); 
    response.setHeader("Content-Disposition", "attachment; filename=\"my.xls\"");     

    HSSFWorkbook workbook = new HSSFWorkbook(); 

    HSSFSheet sheet = workbook.createSheet(); 
    HSSFRow row = sheet.createRow(0); 
    HSSFCell cell = row.createCell(0); 
    cell.setCellValue(0.0); 

    FileOutputStream out = new FileOutputStream("my.xls"); 
    workbook.write(out); 
    out.close(); 
} 

ProjectReportBean.java

public void getReportData() { 
    try { 
     FacesContext ctx = FacesContext.getCurrentInstance(); 
     ExternalContext ectx = ctx.getExternalContext(); 
     HttpServletRequest request = (HttpServletRequest) ectx.getRequest(); 
     HttpServletResponse response = (HttpServletResponse) ectx.getResponse(); 
     RequestDispatcher dispatcher = request.getRequestDispatcher("/ExportExcelReports"); 
     dispatcher.forward(request, response); 
     ctx.responseComplete(); 
    } catch (Exception e) {} 
} 

index.xhtml

<h:form id="reportsForm"> 
    <h:outputLabel for="report" value="Reports" /><br /> 
    <h:selectOneMenu id="report" value="#{projectReportBean.selectedReport}" required="true" requiredMessage="Select Report"> 
     <f:selectItem itemLabel="---" noSelectionOption="true" /> 
     <f:selectItems value="#{projectReportBean.reports}" /> 
    </h:selectOneMenu> 

    <p:commandButton action="#{projectReportBean.getReportData}" value="Export" update="revgrid" />      
</h:form> 

답변

25

이 두 가지 문제가 있습니다.

첫 번째 문제점은 <p:commandButton>이 기본적으로 Ajax 요청을 전송한다는 것입니다. 이 요청은 JavaScript 코드에 의해 시작됩니다. 그러나 JavaScript는 파일 다운로드가 포함 된 응답으로는 아무 것도 할 수 없습니다. 보안 제한으로 인해 다른 이름으로 저장 대화 또는 뭔가를 생성 할 수 없습니다. 응답은 기본적으로 완전히 무시됩니다.

당신은 버튼이 정상 동기 HTTP 요청을 발사 있도록 아약스 해제 <p:commandButton>ajax="false"를 추가해야하거나 표준 <h:commandButton>하여 교체해야합니다.

<p:commandButton ajax="false" ... /> 

또는

<h:commandButton ... /> 

두 번째 문제는 서블릿이 대신 서버의 작업 디렉토리에 저장되어있는 로컬 파일, 엑셀 전혀 응답 파일을 작성하지 않는다는 것입니다. 기본적으로 HTTP 응답은 이 아닙니다.입니다. WorkBook#write() 메소드에 HttpServletResponse#getOutputStream()을 전달해야합니다.

workbook.write(response.getOutputStream()); 

관련없는 메모에서 서블릿이 여기에 얼마나 유용할지 궁금합니다. JSF 밖에서 다시 사용 하시겠습니까? 그렇지 않다면 서블릿에 전혀 디스패치하지 않아도되지만 bean의 액션 메소드에서 같은 코드를 실행하면된다. 그 빈 catch 블록도 좋지 않습니다. 난 그냥 방법으로 throws로 그것을 선언하거나 적어도 new FacesException(e)로 그것을 다시 던지십시오. 의견에 따라


업데이트 당신은 모든 서블릿에 관심이 없을 것 같다. 다음은 JSF 작업 메소드에서 Excel 파일을 프로그래밍 방식으로 보낼 수있는 방법을 약간 재 작성한 것입니다.

public void getReportData() throws IOException { 
    HSSFWorkbook workbook = new HSSFWorkbook(); 
    HSSFSheet sheet = workbook.createSheet(); 
    HSSFRow row = sheet.createRow(0); 
    HSSFCell cell = row.createCell(0); 
    cell.setCellValue(0.0); 

    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    ExternalContext externalContext = facesContext.getExternalContext(); 
    externalContext.setResponseContentType("application/vnd.ms-excel"); 
    externalContext.setResponseHeader("Content-Disposition", "attachment; filename=\"my.xls\""); 

    workbook.write(externalContext.getResponseOutputStream()); 
    facesContext.responseComplete(); 
} 
+0

저는 서블릿을 사용하고 싶지 않습니다. 나도 그랬다고 생각 했어. 나는이 일을 얻은 후에 도전적으로 변화를 주시한다. –

+1

이 경우 다시 쓰기 제안에 대한 대답 업데이트를 확인하십시오. 'ExternalContext'는 많은 위임 메소드를 가지고 있습니다. 그들을 사용하십시오. http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html 궁극적으로 JSF 코드에서 ** zero **'javax.servlet' 가져 오기로 끝내기를 원합니다. – BalusC

+0

그냥 서블릿없이 일하고있어. 정말 도움을 주셔서 감사합니다. –

0

또한 PrimeFaces FileDownload를 사용하여 살펴볼 것을 권장합니다. 구조에 따라이 모든 것을 훨씬 쉽게 할 수 있습니다. ContentStream을 제공 할 수있는 관리 Bean 만 서블릿을 작성할 필요는 없습니다.

서블릿이 이미 작성되었으므로 변경해야 할 점이 없으므로 생각해보십시오.

1

여기에 내가 전에 썼다.

xhtml;

<h:panelGrid id="viewCommand" style="float:right;" > 
         <p:commandButton value="Export Excel" icon="ui-icon-document" 
          ajax="false" actionListener="#{xxx.export2Excel}" 
          rendered="#{xxx.showTable}"> 
          <p:fileDownload value="#{xxx.exportFile}" 
           contentDisposition="attachment" /> 
         </p:commandButton></h:panelGrid> 

자바 측 (POI 포함);

protected void lOBExport2Excel(List table) throws Throwable { 
    Row row = null; 
    Cell cell = null; 
    try { 

     Workbook wb = new HSSFWorkbook(); 
     HSSFCellStyle styleHeader = (HSSFCellStyle) wb.createCellStyle(); 
     HSSFFont fontHeader = (HSSFFont) wb.createFont(); 
     fontHeader.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD); 
     styleHeader.setFont(fontHeader); 
     Sheet sheet = wb.createSheet("sheet"); 
     row = sheet.createRow((short) 0); 

     for (int i = 0; i < columnNames.size(); i++) { 
      cell = row.createCell(i); 
      cell.setCellValue(columnNames.get(i)); 
      cell.setCellStyle(styleHeader); 
     } 

     int j = 1; 

     for (DBData[] temp : tabularData) { 
      row = sheet.createRow((short) j); 
      for (int k = 0; k < temp.length; k++) { 
       HSSFCellStyle styleRow = (HSSFCellStyle) wb.createCellStyle(); 
       HSSFFont fontRow = (HSSFFont) wb.createFont(); 
       fontRow.setBoldweight(HSSFFont.BOLDWEIGHT_NORMAL); 
       styleRow.setFont(fontRow); 
       cell = row.createCell(k); 
       setStyleFormat(temp[k].getDataType(), styleRow, wb); 
       cell.setCellValue(temp[k].toFullString()); 
       cell.setCellStyle(styleRow); 
      } 

      j++; 
     } 

     String excelFileName = getFileName("xls"); 

     FileOutputStream fos = new FileOutputStream(excelFileName); 
     wb.write(fos); 
     fos.flush(); 
     fos.close(); 

     InputStream stream = new BufferedInputStream(new FileInputStream(excelFileName)); 
     exportFile = new DefaultStreamedContent(stream, "application/xls", excelFileName); 


    } catch (Exception e) { 
     catchError(e); 
    } 

} 
+0

전체 작업 코드 – spt

+0

@spt를 "Java side with POI"라는 제목으로 추가 된 작업 데이터로 유지할 수 있습니까? – newuserua