开发时时常遇到下载的功能,如果后端设计的是get请求,我们只需采用超链接的方式,让浏览器自动下载。但是post请求的时候,后端返回的是一个文件流,如下图:
而请求头里面的content-type也跟平常的application/json;charset=UTF-8不一样:
所以我们根据请求头的不同,可以将代码统一封装在request.js里面:(可以查看上一篇封装方法)
if (response.headers['content-type'] === 'application/octet-stream;charset=utf-8') { // 下载流文件
let content = response.headers['content-disposition']
let index = content.indexOf('fileName=')
let fileName = content.substring(index + 9) // 截取文件名
fileName = decodeURIComponent(fileName)
if ('download' in document.createElement('a')) { // 非IE下载
let url = window.URL.createObjectURL(new Blob([response.data]))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
} else { // IE10+下载
navigator.msSaveBlob(new Blob([response.data]), fileName)
}
}
这里用了Blob对象,将从服务器接受到的文件流创建一个Blob对象,然后创建一个URL来访问它,使用URL对象的createObjectURL方法,并将该url作为a标签的链接目标,然后去触发a标签的点击事件从而实现下载。由于window.URL.createObjectURL不兼容IE10以下,所以我们用navigator.msSaveBlob()处理。window.URL.createObjectURL对各浏览器的兼容版本如下:
然后,我们记得把responseType改为blob,因为默认是json:
export function studentExport (params) {
return request({
url: 'url',
method: 'post',
data: params,
responseType: 'blob',
showLoading: true
})
}