如何以“正确”的方式从servlet发送文件?

时间:2011-04-27 14:37:34

标签: http file servlets file-io

我正在尝试从http servlet向用户发送文件。 servlet运行一些识别测试(在请求上),然后向客户端发送一个文件。

这通常有效,但现在我打开我的TOMCAT服务器重定向到https,当我尝试访问servlet并从IE6或IE8下载文件时它失败了,我得到了这个例外:

java.lang.IllegalStateException: Cannot forward after response has been committed

(在localhost.log上)

ClientAbortException:  java.net.SocketException: Connection reset by peer: socket write error

(在servlet日志中)

执行发送(简化)的代码:

private void sendFile(HttpServletResponse response, byte[] file, String clientFileName)
{
    ServletOutputStream op = null;

    setContentType(response);
    response.setHeader("Content-Disposition", "attachment; filename=\"" + clientFileName + "\"");
    // send byte array to output buffer. 
    op = response.getOutputStream();

    // Content Length must be set after all processing done.
    response.setContentLength((int) file.length);   
    op.write(file);
}

这是从servlet发送文件的正确方法吗?什么是最好的方式?

谢谢!

更新

在此链接中使用@BalusC artice中的代码: http://balusc.blogspot.com/2007/07/fileservlet.html

这使它成功。

从Gmail使用IE6-IE8时仍然无效,因为gmail会在这些浏览器的下载过程中添加过滤阶段。

更新2

问题似乎与Gmail + Internet Explorer 6-8有关。 我假设gmail正在进行重定向(如果你在点击邮件中的链接后查看页面上的url,那实际上非常明显)。 Client-Pull技术是我唯一的解决方案吗?

1 个答案:

答案 0 :(得分:0)

问题的解决方案是“Client-Pull”技术。 通过向标头添加Refresh值,我们会让浏览器询问该文件。

这是我能够达到的唯一解决方案,克服了当从电子邮件中按下链接时gmail将使用重定向的事实。

在代码中我这样做了:

response.setHeader("Refresh", "3; URL=\"" + url.toString() + "\"");
forwardToJSP(request, response, "waitForBrowserRefreshPage.jsp");

含义 - 3秒后询问用户指定的URL,然后将该文件传递给客户端。 forwardToJSP方法显示“您将很快转发,此处链接如果失败”消息。