Prasanta
Prasanta

Reputation: 29

how to dynamically generate pdf using servlet

I am generating a pdf using JasperReports in JSP, servlet. I am passing string parameter to the report. When I try to generate single pdf, the pdf is generated nicely but when I try to generate two pdf, for the 1st parameter, pdf is generated but for the 2nd parameter, pdf is not generate.

I'm passing the parameters through a loop.

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

}

Upvotes: 0

Views: 3708

Answers (3)

Met
Met

Reputation: 3172

There are ways to send multi-files in a response but it is inconsistent among browsers. I believe the best approach would be to return a pdf in case of a single file and a zip file in case of multi-files in case you want that single file to open directly in a browser.

I changed your code to return a zip file containing the reports but you should cater for the hard coded strings you have there(seller_name) and also move some functionality to other classes rather than a single method.

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) {                
        }
    }
}

I hope it helps!

Upvotes: 2

Santosh
Santosh

Reputation: 17923

Some comments/suggestion

  1. The response of the servlet is per request. i.e. one request followed by one response.
  2. You are closing the ServletOutputSteam at the end of loop and hence stopping any further responses.
  3. You approach might now work for multiple PDF. One way out is create a list of PDF in the loop, create zip of all the PDFs and send that to the end user.

Upvotes: 1

FrancescoAzzola
FrancescoAzzola

Reputation: 2654

If you want to generate two pdf using the same output stream is impossible. You can generate only one file using an output stream.

If you want to generate 2 or more pdf file i suggest you to create a zip file and write it in the output stream.

Analyzing your code it is clear you can't generate two files because during the loop you close the output stream and flush the data.

You should obtain in such way a Response already commeted or something like that.

Upvotes: 0

Related Questions