导出到Excel JSF和PrimeFaces

使用JDK 1.6,JSF 2.1,PrimeFaces 2.2.1,POI 3.2和Apache Tomcat 7

我正在尝试设置一个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

  

有两个问题。

第一个问题是默认发送一个Ajax请求。 此请求由JavaScript代码触发。 但是,JavaScript无法对包含文件下载的响应执行任何操作。 由于安全限制,JavaScript无法生成“ 另存为”对话框等。 响应基本上完全被忽略了。

您需要向添加ajax="false"以关闭ajax,以便按钮触发正常的同步HTTP请求,或者您需要用标准的替换它。

  

要么

  

第二个问题是您的servlet根本不会将Excel文件写入响应,而是写入存储在服务器工作目录中的本地文件。 基本上,HTTP响应不包含任何内容 。 您需要将HttpServletResponse#getOutputStream()传递给WorkBook#write()方法。

 workbook.write(response.getOutputStream()); 

在一个不相关的说明中,我想知道servlet在这里是如何有用的。 你想在JSF之外重用它吗? 如果没有,您根本不需要调度到servlet,而只需在bean的action方法中执行相同的代码。 那个空的挡块也不好看。 我只是将它声明为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(); } 

这是我之前写的和工作案例;

xhtml;

     

Java端(带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); } } 

我还建议使用PrimeFaces FileDownload。 根据您的结构,它可以使这一切变得更加容易。 您不必仅创建一个可以提供ContentStream的托管bean的servlet。

既然您已经编写了servlet,那么就没有必要改变,只需要深思熟虑。