没有内容长度的响应附件无法在浏览器中打开(IE,FF)

huangapple go评论65阅读模式
英文:

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+"\"");

huangapple
  • 本文由 发表于 2020年9月16日 15:33:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/63915195.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定