0

堆栈:JBoss AS上的JSF + PrimeFacesJasperReports

我一直在使用 JasperReports 以 PDF 格式导出模式,过程分为三个步骤:

[1] 从战争中的一条路径获取已编译的Jasper报告

[2] 将JasperPrint对象放在会话上

[3] 重定向到PdfServlet的 URL

因此,当来自 GUI 的用户单击p:commandButton时,将调用经过 [1]、[2] 和 [3] 的支持 bean 的方法,如以下示例代码所示:

xhtml 文件:

<p:commandButton ajax="false" action="#{indexController.exportPDF}" value="Export PDF"/>

支持 bean 代码:

private void putPrintObjectInSession() throws JRException {
    ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
    ServletContext context = (ServletContext) externalContext.getContext();
    String reportFileName = context.getRealPath("/reports/PrimeNumbersReport.jasper");
    File reportFile = new File(reportFileName);
    if (!reportFile.exists())
        throw new JRRuntimeException(".jasper file not found in the war.");
    Map parameters = new HashMap();
    parameters.put("ReportTitle", "2nd Prime Numbers Report");
    parameters.put("BaseDir", reportFile.getParentFile());
    JasperPrint jasperPrint = 
            JasperFillManager.fillReport(
                      reportFileName, 
                      parameters, 
                      getSQLConnection()
                    );
    ((HttpSession) externalContext.getSession(false)).setAttribute(BaseHttpServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE, jasperPrint);
}

public String exportPDF() throws IOException, JRException {
    putPrintObjectInSession();
    FacesContext facesContext = FacesContext.getCurrentInstance();  
    ExternalContext externalContext = facesContext.getExternalContext();  
    externalContext.redirect("servlets/pdf");
    return null;
}

I have two questions:

[i] do you see any obvious code smells or limitations with this approach?

[ii] with the example code above both Chrome and Conkeror can save the report but the default filename they present to the user for saving the file is simply "pdf". How can I configure that to a meaningful name (e.g. "report-2012-08-23c.pdf") ?

4

1 回答 1

1

As to your concrete problem with the "Save as" filename, it defaults to the last path in the request URL (which is in case of /servlets/pdf indeed just pdf), unless otherwise specified in Content-Disposition header.

The problem is not directly caused by your JSF code (although it is at its own kind of odd, but that's a different problem/question), but more in the servlet which is been mapped on /servlets/pdf. To set the desired "Save as" filename, you need to add the following line before writing any byte to the response:

response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");

You can if necessary replace attachment by inline if you want to display it by default inline.

The Internet Explorer browser, however, ignores this value and sticks to using the last path in the request URL. So to cover that browser as well, you'd need to include the desired filename in the request URL yourself and change the servlet mapping.

E.g.

String filename = "report-2012-08-23c.pdf";
externalContext.redirect("servlets/pdf/" + filename);

with

@WebServlet("/servlets/pdf/*") // instead of @WebServlet("/servlets/pdf")

With this URL pattern, the filename is inside the servlet available by

String filename = request.getPathInfo().substring(1);
于 2012-08-24T11:23:16.383 回答