先说两个比较古老的js下载方式,
1. window.open(src)和window.location = src
2. form表单提交
这两个方式都有局限性,对于需要传递大量参数的下载请求,可以这样写:
this.http.post(`${this.uri}/exportdata.file`, params, {responseType: 'blob'}).subscribe(data => {
const link = document.createElement('a');
const blob = new Blob([data], {type: 'application/zip'});
link.setAttribute('href', window.URL.createObjectURL(blob));
link.setAttribute('download', new Date().getTime() + '.zip');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
这里通过设置 responseType: 'blob' 获取了文件的二进制流,再通过a标签的方式模拟点击下载。
这种下载方式有两点需要注意:
1. 下载的文件格式需要确定
上面的例子下载的是zip格式,如果是其他格式,需要改变Content-Type(代码第三行) 以及 文件名后缀(第五行)。比如:
'doc' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
2. 文件名是前端命名还是后端命名
前端命名的话上面的代码就可以了,如果需要后端命名,首先需要后端在响应头中带上文件名,比如:
Content-disposition: attachment; filename=file_201807201030327711.zip
再对上面的post请求做一下修改:
this.http.post(`${this.uri}/exportdata.file`, params, {responseType: 'blob', observe: 'response'}).subscribe(data => {
const link = document.createElement('a');
const blob = new Blob([data.body], {type: 'application/zip'});
link.setAttribute('href', window.URL.createObjectURL(blob));
link.setAttribute('download', data.headers.get('Content-disposition').split('filename=')[1]);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
通过设置 observe: 'response' 获取到返回的响应头,再获取其中的文件名。