JS下载文件两种方式总结:
下载文件主要分为两种形式,具体使用哪种方式取决于后台;
1.如果后台服务器的静态目录有可供下载的静态资源,后台接口返回文件路径,直接window.location.href=url或者window.open(url)或者创建a标签并指定a.href=url模拟点击进行下载即可;
2.如果后台服务器无可供下载的静态资源,返回的是一个文件流(response-type: application/octet-stream;charset=UTF-8 ),则使用第二种方式(将文件写入内存,并且创建a元素,a链接href属性指向内存中的文件,download属性指向要下载的文件名,模拟a元素的点击事件进行下载然后移除a元素)。
本文主要说明采用文件流的方式下载文件。
一、后台服务器有静态资源且是固定的文件名(GET方式下载文件)
window.location.href="http://www.域名/template.xlsx(请求返回的url地址)"
二、后台返回文件流
方案1:采用FileReader读取二进制流,下载读取后的结果
import axios from 'axios'
axios.post(this.$globalConf.atapPathPrefix + '/system/indicator/export', postParams, { responseType: 'blob' }).then(res => {
let blob = res.data;
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = function(e) {
let a = document.createElement('a');
let fileName = res.headers["content-disposition"] ? res.headers["content-disposition"].split(';')[1].split('=')[1] : new Date().getTime() + '.xlsx'
a.download = decodeURIComponent(fileName)//解码
a.href = e.target.result;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
})
方案二:通过URL.createObjectURL读取二进制流并返回一个对象URL,原理同上
import axios from 'axios'
axios.post(this.$globalConf.atapPathPrefix + '/system/indicator/export', postParams, { responseType: 'blob' }).then(res => {
//这里res.data是返回的blob对象,即对应的二进制流
let blob = res.data
let downloadElement = document.createElement('a');
let href = window.URL.createObjectURL(blob); //创建下载的链接
let fileName = res.headers["content-disposition"] ? res.headers["content-disposition"].split(';')[1].split('=')[1] : new Date().getTime() + '.xlsx'
downloadElement.href = href;
downloadElement.download = decodeURIComponent(fileName)//解码
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href); //释放掉blob对象
})
可能出现的问题:
无法获取headers的content-disposition字段
本次请求获取到fileName如下:
解决办法
在服务端设置header
Access-Control-Expose-Headers: Content-Disposition
(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。