0

我在JSP servlet中使用JasperReports生成 pdf。我将字符串参数传递给报告。当我尝试生成单个 pdf 时,生成的 pdf 很好,但是当我尝试生成两个 pdf 时,对于第一个参数,生成 pdf,但对于第二个参数,不生成 pdf。

我通过循环传递参数。

String array[]={"1233","234"};
HashMap params = new HashMap();
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection cn=DriverManager.getConnection("jdbc:oracle:thin:@103.179.1.218:1521:tims","scoot","tiger");

for(int i=0;i<array.length;i++) {
    params.put("seller_name",array[i]);

    JasperDesign jasperDesign = JRXmlLoader.load(getServletContext().getRealPath("/")+"report\\CForm.jrxml");
    JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
    JasperPrint jasperprint = JasperFillManager.fillReport(jasperReport,params, cn);
    byte[] pdfasbytes = JasperExportManager.exportReportToPdf(jasperprint);
    ServletOutputStream outstream=response.getOutputStream();
    response.setContentType("application/pdf");
    response.setContentLength(pdfasbytes.length);
    String fileName="report"+i+".pdf";
    response.setHeader("Content-disposition", "attachement; filename="+fileName);
    outstream.write(pdfasbytes);
    JRExporter exporter = new JRPdfExporter();
    exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperprint);
    exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outstream);
    params.clear();

}
4

3 回答 3

2

有一些方法可以在响应中发送多个文件,但在浏览器之间是不一致的。我相信最好的方法是在单个文件的情况下返回一个 pdf,在多个文件的情况下返回一个 zip 文件,以防您希望该单个文件直接在浏览器中打开。

我更改了您的代码以返回包含报告的 zip 文件,但您应该满足那里的硬编码字符串(seller_name),并将一些功能移动到其他类而不是单个方法。

protected void processRequest(HttpServletRequest request, HttpServletResponse response) {
    ZipOutputStream zipfile = null;

    try {
        String array[] = {"1233", "234"};
        HashMap params = new HashMap();

        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection cn = DriverManager.getConnection("jdbc:oracle:thin:@103.179.1.218:1521:tims", "scoot", "tiger");

        // Wrap the servlet output stream with a zip output stream
        zipfile = new ZipOutputStream(response.getOutputStream());

        for (int i = 0; i < array.length; i++) {
            params.put("seller_name", array[i]);

            JasperDesign jasperDesign = JRXmlLoader.load(getServletContext().getRealPath("/") + "report\\CForm.jrxml");
            JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);                
            JasperPrint jasperprint = JasperFillManager.fillReport(jasperReport, params, cn);

            byte[] pdfAsBytes = JasperExportManager.exportReportToPdf(jasperprint, params, cn);

            // Create and add the zip entry 
            ZipEntry zipentry = new ZipEntry("report" + i + ".pdf");                                
            zipfile.putNextEntry(zipentry);                
            zipfile.write(pdfAsBytes);                                
        }            

        // Add the response headers
        response.setHeader("Content-disposition", "attachement; filename=" + UUID.randomUUID().toString() + ".zip");                
        response.setContentType("application/zip");            
    } catch (Exception ex) {
        log("An error occured", ex);
    } finally{
        try {
            // Flush the stream
            zipfile.flush();
        } catch (Exception e) {                
        }

        try {
            // Close the stream
            zipfile.close();
        } catch (Exception e) {                
        }
    }
}

我希望它有帮助!

于 2012-08-28T16:31:42.673 回答
1

一些意见/建议

  1. servlet 的响应是每个请求的。即一个请求后一个响应。
  2. 您将在循环结束时关闭 ServletOutputSteam,从而停止任何进一步的响应。
  3. 您的方法现在可能适用于多个 PDF。一种方法是在循环中创建一个 PDF 列表,创建所有 PDF 的 zip 并将其发送给最终用户。
于 2012-08-28T11:37:37.017 回答
0

如果要使用相同的输出流生成两个 pdf 是不可能的。您只能使用输出流生成一个文件。

如果您想生成 2 个或更多 pdf 文件,我建议您创建一个 zip 文件并将其写入输出流。

分析您的代码很明显您无法生成两个文件,因为在循环期间您关闭输出流并刷新数据。

您应该以这种方式获得一个 Response 已经 commeted 或类似的东西。

于 2012-08-28T11:27:10.677 回答