2011-06-29 177 views
44

一切工作正常,但只有当文件很小,大约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(); 
+0

设置内容类型应该这样做。它是哪个浏览器? –

+0

哪个浏览器? Octet-stream应该是正确的答案,但IE的旧版本用于尝试和“嗅探”内容类型,而不管Web服务器告诉它什么 – Paolo

+0

chrome,ff 3.6,以及其他可能... – dieeying

回答

60

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

因此,你的方法应该写成如下(这将无法编译,因为它仅仅是一种表示):

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或HTTP调试代理(如Fiddler或WebScarab)查看网络流量来确认此情况。

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

设置响应的内容类型被发送到客户端,如果响应尚未提交。给定的内容类型可能包含字符编码规范,例如text/html; charset = UTF-8。如果在调用getWriter之前调用此方法,则只会根据给定的内容类型设置响应的字符编码。

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

...

+0

应用程序/强制下载是一个黑客,而不是一个标准:http://www.media-division.com/the-right-way-to-handle-file -downloads-in-php/ –

+0

@ChristopheRoussy,没有人声称是这样的。停止在这里发送垃圾邮件。 –

+2

我想通知其他SO用户有关这是一个黑客攻击,以及它如何工作,因为这是没有提到任何地方,这是一个解释:因此:http://stackoverflow.com/questions/10615797/utility-of-http-header -content-type-application-force-download-for-mobile –

3

这是一个PHP脚本,它与每一个我测试过的浏览器完美地解决了这个问题(因为3.5,IE8 + FF,铬)

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

所以就我所看到的,你”重新做正确的事情。你有没有检查你的浏览器设置?

+0

我爱不释手... – f1sh

+5

我猜想这是“你正在做的一切正确”,烧毁了你。接受的答案明确了什么是不正确的。 –

+0

应用程序/强制下载是一个黑客,而不是一个标准 –

4

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

+0

这是一个重要的信息位 - 学会了艰难的道路:) – ragebiswas

相关问题