在Internet Explorer中使用ServletOutputStream通过HTTPS从Servlet返回CSV文件

Bri*_*ian 6 java servlets java-ee

我有一个Servlet,它返回一个在Internet Explorer和Firefox中通过HTTP"工作"的csv文件.当我通过HTTPS执行相同的Servlet时,只有firefox继续通过HTTPS下载csv文件.我认为这不一定是MSDN上描述的Internet 6或7问题:

消息是:

Internet Explorer无法从mydomain.com下载data.csv Internet Explorer无法打开此Internet站点.请求的网站不可用或无法找到.请稍后再试.

请注意,此消息后该网站仍处于"启动"状态,您可以继续浏览该网站,只需下载提示此消息的CSV即可.我已经能够通过IE浏览器从其他j2ee应用程序访问类似的文件,所以我相信这是我们的代码. 我们不应该关闭bufferedOutputStream吗?

UPDATE

是关闭还是不关闭输出流: 我在java团队论坛上问了这个问题,讨论也很有见地.最后,似乎没有容器应该依赖'client'(在这种情况下是你的servlet代码)来关闭这个输出流.因此,如果未能关闭servlet中的流导致问题,则更多地反映了servlet容器的不良实现而不是代码.我选择了来自Sun,Oracle和BEA的IDE和tortortials的行为,以及它们是否在关闭流时也不一致.

关于IE特定行为:在我们的案例中,单独的产品"Oracle Web Cache"引入了额外的标头值,这些标题值仅影响Internet Explorer,因为IE实现了"无缓存"要求(参见MSDN文章).代码是:

public class DownloadServlet extends HttpServlet {
    public void doGet(HttpServletRequest request, 
                      HttpServletResponse response) throws ServletException, 
                                                           IOException {
        ServletOutputStream out = null;
        ByteArrayInputStream byteArrayInputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        try {
            response.setContentType("text/csv");
                        String disposition = "attachment; fileName=data.csv";
            response.setHeader("Content-Disposition", disposition);

            out = response.getOutputStream();
            byte[] blobData = dao.getCSV();

            //setup the input as the blob to write out to the client
            byteArrayInputStream = new ByteArrayInputStream(blobData);
            bufferedOutputStream = new BufferedOutputStream(out);
            int length = blobData.length;
            response.setContentLength(length);
            //byte[] buff = new byte[length];
             byte[] buff = new byte[(1024 * 1024) * 2];

            //now lets shove the data down
            int bytesRead;
            // Simple read/write loop.
            while (-1 != 
                   (bytesRead = byteArrayInputStream.read(buff, 0, buff.length))) {
                bufferedOutputStream.write(buff, 0, bytesRead);
            }
            out.flush();
            out.close();

        } catch (Exception e) {
            System.err.println(e); throw e;

        } finally {
            if (out != null)
                out.close();
            if (byteArrayInputStream != null) {
                byteArrayInputStream.close();
            }
            if (bufferedOutputStream != null) {
                bufferedOutputStream.close();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Arn*_*ter 5

我真的很困惑你的"从背部通过乳房到头部"的写作机制.为什么不简单(servlet输出流将是bufferend,那是容器的东西):

byte[] csv = dao.getCSV();
response.setContentType("text/csv");
response.setHeader("Content-Disposition", "attachment; filename=data.csv"));
reponse.setContentLength(csv.length);
ServletOutputStream out = response.getOutputStream();
out.write(csv);
Run Code Online (Sandbox Code Playgroud)

也不需要刷新输出流也不需要关闭.

标题内容不应该被IE解析为区分大小写,但是谁知道:不要使用camelcase fileName.接下来的问题是编码.CSV是文本,因此您应该使用getWriter()或g etOutputStream(),并将内容类型设置为"text/csv; charset = UTF-8".但是dao应该将CSV提供为String而不是byte [].

servlet代码与HTTPS无关,因此协议与服务器端无关.您可以使用HTTP测试来自localhost的servlet.

您的应用程序中的过滤器如何?例如,过滤器可以将HTTP标头(或作为页脚)设置为具有高速缓存控制.