下载Safari文件

8

我正在尝试触发文件下载,但在Safari浏览器上遇到了问题(在FireFox和Chrome浏览器上正常工作)。
这是我的Java代码:

  @RequestMapping(method = RequestMethod.GET, produces = "text/csv")
  @ResponseBody
  public String getReports(
      final HttpServletResponse response,
      final @RequestParam String data) throws ParseException {
    response.setHeader("Content-type", "text/csv; charset=utf-8");
    response.setHeader("Content-Disposition","attachment; filename='view.csv'");
    String csv = exportCurrentService.extractMatrix(data);
    response.setContentLength(csv.length());

    return csv;
  }

这是我的客户端代码:

  downloadURI(url, name) {
    const a = document.createElement('a');
    a.href = url;
    a.download = name;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
  }

在Safari中,响应会被打印在屏幕上(在同一页中加载)。

注意:我已经尝试了stackoverflow上提供的其他方法,但每种方法都有它自己的问题。

更新: 在响应头中,我看到Content-Disposition被设置为inline而不是attachment。为什么会这样?

我做错了什么?


你能否在Safari中使用Web检查器获取请求和响应头,并将它们添加到你的问题中? - Stobor
它可以在所有浏览器中下载,但没有文件扩展名和文件名。 - vlio20
可以从其他网站下载,不要认为这是问题所在。 - vlio20
你的意思是说从其他网站下载CSV文件没有问题吗?唉,现在手头没有Mac真是一个错误的时间。:( - Chad
请尝试使用此处定义的解决方案:http://stackoverflow.com/questions/31408065/cant-download-file-browser-opens-it-instead。 - Chad
显示剩余5条评论
3个回答

1

这段代码无法编译,它只是表示你应该做什么。

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");
    //this is from another answer I saw awhile ago while trying to do the same thing
}

这是我在尝试做同样事情时看到的另一篇文章。原作者是 Vineet Reynolds。

我是 SO 的新手,请告知我是否存在不好的实践。


1

尝试不使用@ResponseBody,而是使用produces = MediaType.APPLICATION_JSON_UTF8_VALUE


但我想要它作为csv格式,而不是json。 - vlio20
你可以尝试使用你的类型(text/csv)。 通过@ResponseBody注释,您将Content-type标头设置为text/plain。 请参阅:https://dev59.com/CF0a5IYBdhLWcg3wPWpN#30549204 - NikNik
我已经尝试过了,但看起来 Content-Disposition 被设置为 inline(在响应头中通过开发者工具查看)。 - vlio20

0

我的服务位于路由模块之后(该模块是所有微服务的代理)。问题出在这个模块(代理)上,它覆盖了微应用服务的标头和 cookie。

按照问题描述中所述的设置代码解决了这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接