Search code examples
javaservletsjasper-reports

Response Attachment without Content Length won't open in browser (IE,FF)


I have a servlet that generates csv report and sends it to the client (browser) as an attachment.

Below is the part of servlet's the code:

private void generateCSVOutput(
            HttpServletResponse response,
            java.util.Map parameters,
            JasperPrint jasperPrint) throws JRException, NamingException, SQLException, IOException {
            String fileName = makeFileName(parameters, ".csv");
            response.setHeader("Content-disposition","filename=\""+fileName+"");
            byte[] bytes = null;
            JRCsvExporter exporter = new JRCsvExporter();
            ByteArrayOutputStream csvReport = new ByteArrayOutputStream();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, csvReport);
            exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "sample.csv");
            exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, ";");
            exporter.exportReport();
            bytes = csvReport.toByteArray();
            response.setContentType(getMimeType("csv"));
            response.setContentLength(bytes.length);
            ServletOutputStream ouputStream = response.getOutputStream();
            ouputStream.write(bytes, 0, bytes.length);
            ouputStream.flush();
            ouputStream.close();

    }

Now, to avoid memory consumption I've decided to stream the report's output directly to response thus avoiding the use of ByteArrayOutputStream.

The side effect is that I no longer have the information about the contents length. So contents length is not set. The resulting code is:

private void generateCSVOutput(
            HttpServletResponse response,
            java.util.Map parameters,
            JasperPrint jasperPrint) throws JRException, NamingException, SQLException, IOException {
            String fileName = makeFileName(parameters, ".csv");
            response.setHeader("Content-disposition","filename=\""+fileName+"");
            JRCsvExporter exporter = new JRCsvExporter();
            //ByteArrayOutputStream csvReport = new ByteArrayOutputStream();
            ServletOutputStream ouputStream = response.getOutputStream();
            exporter.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, ouputStream);
            exporter.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, "sample.csv");
            exporter.setParameter(JRCsvExporterParameter.FIELD_DELIMITER, ";");
            exporter.exportReport();
            //bytes = csvReport.toByteArray();
            response.setContentType(getMimeType("csv"));
            //response.setContentLength(bytes.length);
            //ServletOutputStream ouputStream = response.getOutputStream();
            //ouputStream.write(bytes, 0, bytes.length);
            ouputStream.flush();
            ouputStream.close();

    }

However after the change browsers (IE,FF) no longer pop up a dialog to open/save the attachment.

I had an impression that setting the contents length is advised but is not mandatory.

So why the above code does not behave correctly?


Solution

  • turns out that this behavior was caused by the following line:

    response.setHeader("Content-disposition","filename=\""+fileName+"");
    

    the reason was the missing end quote

    response.setHeader("Content-disposition","filename=\""+fileName+"\"");