Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何强制浏览器下载文件?_Java_Servlets_Jakarta Ee - Fatal编程技术网

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

Java 如何强制浏览器下载文件?,java,servlets,jakarta-ee,Java,Servlets,Jakarta Ee,一切正常,但只有当文件很小,大约1MB时,当我尝试使用更大的文件时,比如20MB,我的浏览器会显示它,而不是强制下载,到目前为止,我尝试了许多标题,现在我的代码看起来: PrintWriter out = response.getWriter(); String fileName = request.getParameter("filename"); File f= new File(fileName); InputStream in = new FileInputStream(f); Bu

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

这来自一个php脚本,它完美地解决了我测试过的每个浏览器的问题(3.5版以来的FF、IE8+、Chrome)


就我所知,你做的每件事都是对的。是否检查了浏览器设置?

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

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

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

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

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

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


在写入文件之前设置内容类型和其他标题。对于小文件,内容被缓冲,浏览器首先获取标题。对于大型网站,数据是第一位的。

设置内容类型就可以了。它是哪个浏览器?哪个浏览器?八位字节流应该是正确的答案,但是旧版本的IE用来尝试和“嗅探”内容类型,而不管web服务器告诉我们什么,ff 3.6,或者每隔一段时间……头先,数据后,而不是其他方式!内容处置附件可以做到这一点。请注意,应用程序/强制下载是某种特定的黑客行为,而不是一种标准,请阅读以下内容:我猜是“你做的每件事都是正确的”烧坏了你。被接受的答案清楚地表明了什么是错误的。application/force-download是黑客行为,而不是标准的application/force-download是黑客行为,而不是标准的:@christoroussy,是的,没有人这样声称。停止在此处滥发所有答案。我想通知其他SO用户这是一种黑客行为,以及它是如何工作的,因为这在任何地方都没有提及,以下是关于SO的解释:
header("Content-Disposition: attachment; filename=\"".$fname_local."\"");
header("Content-Type: application/force-download");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($fname));
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");
}