Issue
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+"\"");
Answered By - PKey
Answer Checked By - Candace Johnson (JavaFixing Volunteer)