强制浏览器从URL下载文件为CSV

4

我正在从URL下载一个CSV文件,如何设置特定的响应头来下载我的文件?

期望的响应头:

HTTP/1.1 200 OK
Date: Mon, 29 May 2017 06:03:38 GMT
Content-Type: application/octet-stream
Content-Length: 340
Connection: keep-alive
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Last-Modified: Mon May 29 11:33:38 IST 2017
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
Content-Disposition: attachment; filename="5756913MerchantTransactionFile20170529113338.csv"
Server: Some
Access-Control-Allow-Origin: 
Access-Control-Allow-Origin: 
authorized: true
authorizehtml: true

当前响应头

HTTP/1.1 200 OK
Date: Mon, 29 May 2017 06:16:52 GMT
Server: Apache/2.4.18 (Unix) PHP/5.5.36
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
Access-Control-Max-Age: 1000
Access-Control-Allow-Headers: x-requested-with, Content-Type, origin, authorization, accept, client-security-token
Expires: Tue, 03 Jul 2001 06:00:00 GMT
Last-Modified: Mon May 29 11:46:52 IST 2017
Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0
Pragma: no-cache
Content-Type: application/json
Content-Length: 0
Keep-Alive: timeout=5, max=97
Connection: Keep-Alive

我的代码:

openFile(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {

    }
};
xhttp.open("GET",url, true);
xhttp.send();
  //window.open(url, '_blank')
}

尝试从URL下载CSV文件。请帮我解决问题。我们如何强制浏览器下载文件?

3
你是怎么处理那个假定的CSV文件的?响应头只能由响应代理设置。 - David Hedlund
1
响应头是服务器告诉客户端的内容。客户端唯一可以更改的是请求头,这可能会导致不同的响应。 - Hubert Grzeskowiak
2个回答

2

这里的技巧是将您的数据转换为blob格式,然后在一个带有blob url的锚点标签上模拟点击事件。

var blob = new Blob([content]);

创建一个点击事件。

var evnt =  new Event('click');

然后创建一个如下所示的锚标记并分派事件。
  $("<a>", {
    download: filename,
    href: webkitURL.createObjectURL(blob)
  }).get(0).dispatchEvent(evnt);

这里有一个函数。
 var download = function(filename, content) {
  var blob = new Blob([content]);
  var evnt =  new Event('click');

  $("<a>", {
    download: filename,
    href: webkitURL.createObjectURL(blob)
  }).get(0).dispatchEvent(evnt);
};

使用上述下载功能。

用法:调用download函数,带有两个参数文件名内容

openFile(url) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function(data) {
    if (this.readyState == 4 && this.status == 200) {
      download('file.csv', data);
    }
  };
  xhttp.open("GET", url, true);
  xhttp.send();
  //window.open(url, '_blank')
}

为什么要使用自定义事件?(而且这并不意味着您创建的方式已过时,也不意味着您甚至没有正确初始化它)。当您有xhr.responseType ='blob'选项时,为什么要从xhr响应创建Blob?那么不支持Anchor.download属性的浏览器怎么办? - Kaiido
谢谢更新,我已经添加了新的添加事件方法。此外,这种方法不仅适用于 xhr,它可以接受普通文本内容并帮助下载。这就是为什么 blob 转换在函数内部的原因。而且,这种方法适用于大多数较新的主流浏览器,使用率达到了73%,问题并不特定于浏览器。 - Nadir Laskar

-1
你在发起请求时应该指定正确的Accept头信息。然后服务器会在响应中加入正确的Content-Type头信息。对于你的情况,在创建XMLHttpRequest时,你应该加入这行代码:
xhttp.setRequestHeader("Accept", "text/csv; charset=utf-8");

这不是接受 text/csv 的问题,而是强制下载对话框的问题,这是由于 Content-Disposition 响应头引起的。 - Vivek Athalye
@Vivek,没有提到对话框。只有关于错误响应头的问题。询问的人试图从服务器上修复标头。我提供了可能的解决方案。是服务器应该指定Content-Disposition头和Content-Type。 - Oleg M
问题标题本身包含强制浏览器下载文件 - Vivek Athalye

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