如何强制浏览器下载文件? [英] How to force browser to download file?

查看:113
本文介绍了如何强制浏览器下载文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Everything works fine, but only if file is small, about 1MB, when I tried it with bigger files, like 20MB my browser display it, instead of force to download, I tried many headers so far, now my code looks:

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("
");
}

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();

推荐答案

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

You are setting the response headers after writing the contents of the file to the output stream. This is quite late in the response lifecycle to be setting headers. The correct sequence of operations should be to set the headers first, and then write the contents of the file to the servlet's outputstream.

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

Therefore, your method should be written as follows (this won't compile as it is a mere representation):

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("
");
}

失败的原因是 servlet 发送的实际头可能与您打算发送的不同.毕竟,如果 servlet 容器不知道什么 headers(在 HTTP 响应中出现在 body 之前),那么它可能会设置适当的 headers 以确保响应是有效的;因此,在写入文件后设置标头是徒劳且多余的,因为容器可能已经设置了标头.您可以通过使用 Wireshark 或 HTTP 调试代理(如 Fiddler 或 WebScarab)查看网络流量来确认这一点.

The reason for the failure is that it is possible for the actual headers sent by the servlet would be different from what you are intending to send. After all, if the servlet container does not know what headers (which appear before the body in the HTTP response), then it may set appropriate headers to ensure that the response is valid; setting the headers after the file has been written is therefore futile and redundant as the container might have already set the headers. You could confirm this by looking at the network traffic using Wireshark or a HTTP debugging proxy like Fiddler or WebScarab.

您还可以参考 Java EE API 文档 ServletResponse.setContentType 以了解此行为:

You may also refer to the Java EE API documentation for ServletResponse.setContentType to understand this behavior:

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

Sets the content type of the response being sent to the client, if the response has not been committed yet. The given content type may include a character encoding specification, for example, text/html;charset=UTF-8. The response's character encoding is only set from the given content type if this method is called before getWriter is called.

此方法可能会被重复调用以更改内容类型和字符编码.如果在响应提交后调用此方法无效.

This method may be called repeatedly to change content type and character encoding. This method has no effect if called after the response has been committed.

...

这篇关于如何强制浏览器下载文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆