如何使用servlet动态生成pdf

时间:2012-08-28 11:18:23

标签: java jasper-reports

我使用 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();

}

3 个答案:

答案 0 :(得分: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) {                
        }
    }
}

我希望它有所帮助!

答案 1 :(得分:1)

一些意见/建议

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

答案 2 :(得分:0)

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

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

分析你的代码很明显你不能生成两个文件,因为在循环中你关闭输出流并刷新数据。

你应该以这种方式获得已经被评价的回应或类似的回应。