JasperReports PdfServlet以PDF格式保存报告 - 如何设置浏览器的文件名以提示用户?

时间:2012-08-23 16:06:13

标签: jsf jasper-reports

Stack JBF + PrimeFaces JBoss AS JasperReports

我一直在使用JasperReports以PDF格式导出模式,只需三个步骤:

[1]从 war

中的路径获取已编译的Jasper报告

[2]将 JasperPrint 对象放在会话

[3]重定向到 PdfServlet

的网址

因此,当用户从GUI点击 p:commandButton 时,将调用支持bean的方法,该方法将通过[1],[2]和[3],如下面的示例代码所示:

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]你看到这种方法有任何明显的代码气味或限制吗?

[ii]使用上面的示例代码,Chrome和Conkeror都可以保存报告,但是他们提供给用户保存文件的默认文件名只是“pdf”。如何将其配置为有意义的名称(例如“report-2012-08-23c.pdf”)?

1 个答案:

答案 0 :(得分:1)

对于“另存为”文件名的具体问题,它默认为请求URL中的最后一个路径(如果/servlets/pdf确实只是pdf),除非另有说明Content-Disposition标题。

问题不是由你的JSF代码直接引起的(虽然它本身有点奇怪,但这是一个不同的问题/问题),但在/servlets/pdf上映射的servlet中更多。要设置所需的“另存为”文件名,需要在将任何字节写入响应之前添加以下行:

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

如果您想在默认情况下以内联方式显示attachment,可以根据需要将inline替换为String filename = "report-2012-08-23c.pdf"; externalContext.redirect("servlets/pdf/" + filename);

但是,Internet Explorer浏览器会忽略此值并坚持使用请求URL中的最后一个路径。因此,为了覆盖该浏览器,您需要自己在请求URL中包含所需的文件名并更改servlet映射。

E.g。

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

String filename = request.getPathInfo().substring(1);

使用此URL模式,文件名位于

可用的servlet中
{{1}}