前言:在前端的开发过程中,经常会遇到各种各样的下载文件处理。其中因为不同原因(不同后端的开发习惯, 信息安全原因)等,下载文件的处理也是各有不同。其中包含常见的excel下载, 压缩文件zip下载等,其实处理方法都是基本相同,对于各种形式的文件应该都是可以下载的。
这边对于文件的下载方式进行总结,总的来说只有两种~
1. 后端返回一个url, 前端根据url进行下载
方法1: 创建iframe进行下载
export const downloadFile = url => {
const divFrame = window.parent.document.getElementById('downLoadListFrame')
// 判断是否存在,如果存在先移除,再重新创建
if (divFrame != null) {
window.parent.document.body.removeChild(divFrame)
}
// 重新创建
const iframe = window.parent.document.createElement('iframe')
iframe.setAttribute('id', 'downLoadListFrame')
// download_file.id = "downFrame";
window.parent.document.body.appendChild(iframe)
iframe.setAttribute('src', url)
iframe.style.display = 'none'
const timer = setTimeout(() => {
iframe.setAttribute('src', '')
clearInterval(timer)
}, 30000)
}
方法2: window.open() 进行下载
window.open(url)
特点: 这种方式前端更改不了文件名,请让后端设置好。
2.后端返回文件的blob流,前端解析后下载
方式1:直接对blob解析
const toLocalFile = (data: any, contentType: any, fileName: string) => {
const blob = new Blob([data], { type: contentType });
const url = window.URL.createObjectURL(blob);
// 打开新窗口方式进行下载
// window.open(url);
// 以动态创建a标签进行下载
const a = document.createElement('a');
a.href = url;
a.download = fileName; // 文件名
a.click();
window.URL.revokeObjectURL(url);
};
方式2:直接在请求后进行处理下载
export const download = ({ url, params = '', method = 'post' }) => {
axios({
method,
headers: {'Content-Type': 'application/json;charset=utf-8;'
},
url: url,
data: JSON.stringify(params),
responseType: 'blob'
})
.then(res => {
console.log('res', res, res.data, new Blob([res.data]))
const filename = res.headers['content-disposition']
? res.headers['content-disposition'].split('=')[1]
: `YHQ${moment().format('YYYYMMDDHHmmss')}.xls`
const content = res.data
const blob = new Blob([content])
if (content.type === 'multipart/form-data') {
if ('download' in document.createElement('a')) {
// 非IE下载
const elink = document.createElement('a')
elink.download = filename
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象
document.body.removeChild(elink)
} else {
// IE10+下载
navigator.msSaveBlob(blob, filename)
}
}
})
.catch(err => {
MESSAGE.error(err)
})
}
特点: 前端可以通过download属性设置文件名
ps:通过请求获取文件名,通常会有个小问题,就是后端是把文件名放在res.headers['content-disposition']中,但是常常前端这边却没有显示。
原因为:默认情况下,只有七种 simple response headers(简单响应首部)可以暴露给外部:
解决方法: 如果想要让客户端可以访问到其他的首部信息,可以将它们在 Access-Control-Expose-Headers
里面列出来。(请让后端进行设置)
// 后端设置
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
response.setHeader("Content-Disposition", ...)
另外:如果文件安全性要求较高建议使用Blob方式,避免信息泄露以及恶意攻击下载