2011-10-19 35 views
16

Sử dụng JDK 1.6, JSF 2.1, PrimeFaces 2.2.1, POI 3.2, và Apache Tomcat 7Xuất sang Excel JSF và PrimeFaces

Tôi cố gắng để thiết lập một servlet để cho phép tải về của một tập tin excel dựa trên lựa chọn người dùng. Tài liệu excel được tạo ra khi chạy.

Không có lỗi và mã nào xâm nhập vào servlet.

Tôi nhấp vào nút và không có gì xảy ra. Tôi không sử dụng việc xuất dữ liệu mà PrimeFaces sử dụng vì tôi cần phải sắp xếp lại và định dạng tùy chỉnh trên dữ liệu trong tài liệu 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> 

Trả lời

25

Có hai vấn đề.

Vấn đề đầu tiên là <p:commandButton> gửi theo mặc định một yêu cầu Ajax. Yêu cầu này được kích hoạt bởi mã JavaScript. Tuy nhiên, JavaScript không thể làm bất cứ điều gì với một phản ứng có chứa một tập tin tải về. Do các hạn chế về bảo mật, JavaScript không thể hiển thị hộp thoại Lưu dưới dạng hoặc nội dung nào đó. Phản ứng về cơ bản hoàn toàn bị bỏ qua.

Bạn cần thêm ajax="false" vào <p:commandButton> để tắt ajax để nút kích hoạt yêu cầu HTTP đồng bộ bình thường hoặc bạn cần thay thế bằng tiêu chuẩn <h:commandButton>.

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

hoặc

<h:commandButton ... /> 

Vấn đề thứ hai là servlet của bạn không ghi file Excel để phản ứng chút nào, nhưng thay vào đó vào một tập tin cục bộ được lưu trữ trong thư mục làm việc của máy chủ. Về cơ bản, phản hồi HTTP chứa không có gì. Bạn cần phải vượt qua HttpServletResponse#getOutputStream() theo phương thức WorkBook#write().

workbook.write(response.getOutputStream()); 

Trên ghi chú không liên quan, tôi tự hỏi làm thế nào servlet hữu ích ở đây. Bạn có muốn sử dụng lại nó bên ngoài JSF không? Nếu không, bạn không nhất thiết phải gửi đến servlet chút nào, nhưng chỉ cần thực hiện cùng một mã trong phương thức action của bean. Khối trống catch cũng không đẹp. Tôi chỉ tuyên bố nó là throws trong phương pháp hoặc ít nhất là rethrow nó là new FacesException(e).


Cập nhật theo ý kiến ​​bạn dường như không quan tâm đến các servlet ở tất cả. Dưới đây là một phần nhỏ viết lại cách bạn có thể gửi tệp Excel theo cách lập trình trong một phương thức hành động JSF.

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

tôi không muốn sử dụng servlet. tôi cũng nghĩ vậy. defiantly nhìn vào thay đổi mà sau khi tôi nhận được điều này làm việc. –

+1

Trong trường hợp đó, hãy kiểm tra cập nhật câu trả lời cho đề xuất viết lại. 'ExternalContext' có rất nhiều phương thức ủy nhiệm. Hãy sử dụng chúng. http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html Cuối cùng bạn muốn kết thúc với nhập ** javax.servlet' không nhập ** trong mã JSF của bạn. – BalusC

+0

chỉ có nó hoạt động mà không có servlet. thực sự đánh giá cao sự giúp đỡ. –

0

Tôi cũng khuyên bạn nên xem xét sử dụng Tệp tải xuống PrimeFaces. Tùy thuộc vào cấu trúc của bạn, nó có thể làm cho tất cả điều này dễ dàng hơn rất nhiều. Bạn sẽ không phải tạo một servlet chỉ là một bean được quản lý có thể cung cấp một ContentStream.

Vì bạn đã có servlet được viết mặc dù, không có gì thay đổi, chỉ cần thực phẩm cho suy nghĩ.

1

Đây là điều tôi đã viết trước đó và trường hợp làm việc;

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> 

Mặt Java (có 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

Bạn có thể giữ mã hoạt động hoàn chỉnh – spt

+0

@spt dữ liệu đã hoạt động của nó được thêm vào với chủ đề "Java side (with POI)" không – newuserua

Các vấn đề liên quan