本文介绍了导出到Excel JSF和PrimeFaces的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我想建立一个servlet允许下载基于用户选择一个Excel文件。在运行时创建Excel文档。

没有错误,并且code不进入的servlet。

我按一下按钮没有任何反应。我不使用DataTable出口的PrimeFaces使用,因为我需要做的重新排序和自定义格式的Excel文档中的数据。

ExportExcelReports.java

 保护无效的processRequest(HttpServletRequest的请求,HttpServletResponse的响应)
        抛出了ServletException,IOException异常{
    response.setContentType(应用程序/ vnd.ms - Excel中);
    response.setHeader(内容处置,附件;文件名= \\my.xls \\);    HSSFWorkbook工作簿=新HSSFWorkbook();    HSSFSheet片= workbook.createSheet();
    HSSFRow行= sheet.createRow(0);
    HSSFCell细胞= row.createCell(0);
    cell.setCellValue(0.0);    FileOutputStream中出=新的FileOutputStream(my.xls);
    workbook.write(出);
    out.close();
}

ProjectReportBean.java

 公共无效getReportData(){
    尝试{
        FacesContext中CTX = FacesContext.getCurrentInstance();
        的ExternalContext ECTX = ctx.getExternalContext();
        HttpServletRequest的请求=(HttpServletRequest的)ectx.getRequest();
        HttpServletResponse的响应=(HttpServletResponse的)ectx.getResponse();
        RequestDispatcher的调度=的request.getRequestDispatcher(/ ExportExcelReports);
        dispatcher.forward(请求响应);
        ctx.responseComplete();
    }赶上(例外五){}
}

的index.xhtml

 < H:表ID =reportsForm>
    < H:outputLabel为=报告VALUE =报告/>< BR />
    < H:selectOneMenu用于ID =报告VALUE =#{} projectReportBean.selectedReport所需=真requiredMessage =选择报告>
        < F:选择信息itemLabel =---noSelectionOption =真/>
        < F:selectItems的值=#{} projectReportBean.reports/>
    < /小时:selectOneMenu用于>    <电话号码:行动的commandButton =#{} projectReportBean.getReportData值=导出更新=​​revgrid/>
< /小时:形式>


解决方案

有两个问题。

第一个问题是,<电话号码:&的commandButton GT; 默认发送一个Ajax请求。这个请求由JavaScript code解雇。然而,JavaScript不能做它包含一个文件下载的回应什么。由于JavaScript不能酿出的另存为的对话什么的安全限制。响应基本上是完全忽略。

您需要的ajax =false的添加到<电话号码:的commandButton> 打开AJAX关闭,因此该按钮触发一个正常同步的HTTP请求,或者你需要通过标准来取代它< H:的commandButton>

<电话号码:阿贾克斯的commandButton =假... />

< H:...的commandButton />

第二个问题是,你的servlet不写Excel文件在所有,而是要存储在服务器工作目录的本地文件的响应。基本上,HTTP响应包含的没有的。你需要传递 HttpServletResponse的#的getOutputStream()工作薄#写()方法。

  workbook.write(response.getOutputStream());

在一个不相关的说明,我不知道该servlet是如何用在这里。你想重新使用它JSF外面?如果没有,你不一定需要在所有派遣到servlet,而只是执行相同的code在bean的操作方法。那空块也是不是很好。我只是把它声明为抛出的方法,或者至少重新抛出它作为新FacesException(E)


更新按你似乎没有兴趣在servlet在所有的评论。这里有一个小的重写你怎么可以在JSF action方法以编程方式发送Excel文件。

 公共无效getReportData()抛出IOException
    HSSFWorkbook工作簿=新HSSFWorkbook();
    HSSFSheet片= workbook.createSheet();
    HSSFRow行= sheet.createRow(0);
    HSSFCell细胞= row.createCell(0);
    cell.setCellValue(0.0);    FacesContext中的FacesContext = FacesContext.getCurrentInstance();
    的ExternalContext的ExternalContext = facesContext.getExternalContext();
    externalContext.setResponseContentType(应用程序/ vnd.ms - Excel中);
    externalContext.setResponseHeader(内容处置,附件;文件名= \\my.xls \\);    workbook.write(externalContext.getResponseOutputStream());
    facesContext.responseComplete();
}

Using JDK 1.6, JSF 2.1, PrimeFaces 2.2.1, POI 3.2, and Apache Tomcat 7

I am trying to setup a servlet to allow a download of an excel file based on the user selection. The excel document is created at runtime.

No errors and the code does get into the servlet.

I click the button and nothing happens. I am not using the datatable export that PrimeFaces uses because I need to do reordering and custom formatting on the data in the Excel document.

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>
解决方案

There are two problems.

The first problem is that the <p:commandButton> sends by default an Ajax request. This request is fired by JavaScript code. However, JavaScript can't do anything with a response which contains a file download. Due to security restrictions JavaScript can't spawn a Save As dialogue or something. The response is basically totally ignored.

You need to add ajax="false" to <p:commandButton> to turn ajax off so that the button fires a normal synchronous HTTP request, or you need to replace it by standard <h:commandButton>.

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

or

<h:commandButton ... />

The second problem is that your servlet doesn't write the Excel file to the response at all, but instead to a local file which is stored in server's working directory. Basically, the HTTP response contains nothing. You need to pass HttpServletResponse#getOutputStream() to the WorkBook#write() method.

workbook.write(response.getOutputStream());

On an unrelated note, I wonder how the servlet is useful here. Do you want to reuse it outside JSF? If not, you don't necessarily need to dispatch to the servlet at all, but just execute the same code in bean's action method. That empty catch block is also not nice. I'd just declare it as throws in method or at least rethrow it as new FacesException(e).


Update as per the comments you seem not be interested in the servlet at all. Here's a minor rewrite how you could send the Excel file programmatically in a JSF action method.

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

这篇关于导出到Excel JSF和PrimeFaces的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 06:08