如何强制浏览器下载文件?

一切工作正常,但只有当文件很小,大约1MB,当我用更大的文件,像20MB的我的浏览器显示它,而不是强制下载,我尝试了很多标题到目前为止,现在我的代码看起来:

PrintWriter out = response.getWriter(); String fileName = request.getParameter("filename"); File f= new File(fileName); InputStream in = new FileInputStream(f); BufferedInputStream bin = new BufferedInputStream(in); DataInputStream din = new DataInputStream(bin); while(din.available() > 0){ out.print(din.readLine()); out.print("\n"); } response.setContentType("application/force-download"); response.setContentLength((int)f.length()); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); in.close(); bin.close(); din.close(); 

在将文件的内容写入输出stream之后,您正在设置响应标头。 在设置标题的响应生命周期中,这是相当晚的。 正确的操作顺序应该是首先设置标题,然后将文件的内容写入到servlet的输出stream中。

因此,你的方法应该写成如下(这不会被编译,因为它只是一个表示):

 response.setContentType("application/force-download"); response.setContentLength((int)f.length()); //response.setContentLength(-1); response.setHeader("Content-Transfer-Encoding", "binary"); response.setHeader("Content-Disposition","attachment; filename=\"" + "xxx\"");//fileName); ... ... File f= new File(fileName); InputStream in = new FileInputStream(f); BufferedInputStream bin = new BufferedInputStream(in); DataInputStream din = new DataInputStream(bin); while(din.available() > 0){ out.print(din.readLine()); out.print("\n"); } 

失败的原因是由servlet发送的实际报头可能与您打算发送的不同。 毕竟,如果servlet容器不知道哪些头(在HTTP响应中出现在主体之前),那么它可以设置合适的头以确保响应是有效的; 在文件被写入后设置标题因此是无用的和冗余的,因为容器可能已经设置了标题。 您可以通过使用Wireshark或HTTPdebugging代理(如Fiddler或WebScarab)查看networkingstream量来确认此情况。

您也可以参考ServletResponse.setContentType的Java EE API文档来理解这种行为:

如果响应尚未提交设置发送给客户端的响应的内容types 给定的内容types可以包括字符编码规范,例如text / html; charset = UTF-8。 如果在调用getWriter之前调用此方法,则仅从给定的内容types设置响应的字符编码。

可以重复调用此方法来更改内容types和字符编码。 如果在提交响应之后调用此方法,则此方法无效。

写出文件之前设置内容types和其他标题。 对于小文件,内容被缓冲,浏览器首先获取标题。 对于大数据来说,数据是第一位的。

这是从一个PHP脚本,它解决了我所testing的每个浏览器(FF自3.5,IE8 +,铬)完美的问题,

 header("Content-Disposition: attachment; filename=\"".$fname_local."\""); header("Content-Type: application/force-download"); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize($fname)); 

所以就我所知,你正在做的一切正确。 你有没有检查你的浏览器设置?