英文:
Response Attachment without Content Length won't open in browser (IE,FF)
问题
以下是您要翻译的内容:
我有一个生成 `csv` 报告并将其作为附件发送到客户端(浏览器)的 servlet。
以下是 servlet 代码的一部分:
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();
}
现在,为了避免内存消耗,我决定直接将报告的输出流式传输到响应,从而避免使用 `ByteArrayOutputStream`。
副作用是我不再具有有关内容长度的信息。
因此,未设置内容长度。结果代码如下:
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();
}
然而,更改后,浏览器(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?
答案1
得分: 0
原来,这种行为是由以下这行代码引起的:
response.setHeader("Content-disposition","filename=\"" + fileName + "\"");
问题是缺少了结束引号:
response.setHeader("Content-disposition","filename=\"" + fileName + "\\\"");
英文:
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+"\"");
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论