2011-10-19 51 views
16

使用JDK 1.6,JSF 2.1,PrimeFaces 2.2.1,POI 3.2,和Apache Tomcat 7導出到Excel JSF和PrimeFaces

我試圖建立一個servlet來允許基於該下載的Excel文件用戶選擇。 excel文檔是在運行時創建的。

沒有錯誤和代碼確實進入了servlet。

我點擊按鈕,沒有任何反應。我沒有使用PrimeFaces使用的數據表導出,因爲我需要對Excel文檔中的數據重新排序和自定義格式。

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無法做任何事情。由於安全限制,JavaScript不能產生另存爲對話或其他內容。這個反應基本上被完全忽略了。

您需要添加ajax="false"<p:commandButton>把AJAX關閉,因此該按鈕會正常同步的HTTP請求,或者你需要通過標準<h:commandButton>來取代它。

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

<h:commandButton ... /> 

的第二個問題是,你的servlet沒有寫入Excel文件的響應可言,而是要存儲在服務器的工作目錄中的本地文件。基本上,HTTP響應包含什麼也沒有。您需要將HttpServletResponse#getOutputStream()傳遞給WorkBook#write()方法。

workbook.write(response.getOutputStream()); 

在一個不相關的音符,我不知道該servlet如何在這裏很有用。你想在JSF之外重用它嗎?如果沒有,你不一定需要派發到servlet,而只是在bean的action方法中執行相同的代碼。那空的catch塊也不好看。我只是在方法中聲明它爲throws,或者至少將它重新拋出爲new FacesException(e)


更新按照意見,你似乎不感興趣在servlet的。這裏有一個小小的改寫,您可以通過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

我不想使用servlet。我以爲我也是。在我得到這個工作後,挑釁地看着改變。 –

+1

在這種情況下,請檢查答案更新以獲取重寫建議。 'ExternalContext'有很多委託方法。利用它們。 http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html您最終想要在您的JSF代碼中導入** zero **'javax.servlet'導入。 – BalusC

+0

剛剛得到它沒有servlet的工作。真的很感謝幫助。 –

0

我還建議看看使用PrimeFaces FileDownload。根據你的結構,它可以使這一切變得更容易。你不需要創建一個servlet只是一個可以提供ContentStream的託管bean。

既然你已經寫了servlet,沒有任何改變的地方,只是想一想。

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> 

Java side(with 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端(帶POI)」 – newuserua