文件上传下载是项目中经常会遇到的常规功能,例如静态资源下载、数据导出等等。本文总结了三种针文件下载的方法。
前端实现下载的原理一般是基于a标签下载。浏览器内部提供了钩子,而且在H5当中a标签新增了download属性。浏览器支持,当该属性的链接被点击时,浏览器会以下载文件的方式下载href的属性上的链接 这就是所谓的“钩子”。
1.文件流方式
如果后台服务器无可供下载的静态资源,一般使用文件流方式下载,不至于过多占用服务器资源,一般常用于动态的导出数据等情景。
代码实现
export function PostDownload (url, data) {
return new Promise((resolve, reject) => {
Request
.post(url, data, {
responseType: 'blob' // 必需
})
.then((res) => {
if (res && res.status == 200) {
reject(new Error('Download Failed'))
} else {
// 对后端返回的文件流处理,res.data即后端返回的文件流如上图
const blob = new Blob([res.data])
let filename = data.filename || `${new Date() - 0}.xlsx`;
try {
filename = decodeURI(res.headers['content-disposition'].split(';')[1].split('filename=')[1]);
} catch (e) {
console.log(e)
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(blob, filename);
} else {
const url: any = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(url.href);
document.body.removeChild(link);
resolve()
}
}
})
.catch(() => {
Message.error({
message: 'Download Failed',
duration: 2000
})
})
})
}
注意事项
1)设置响应类型blob
请求头中需设置
responseType:'blob'
,否则下载的文件将解析失败无法打开;
2)filename的获取方式
注意:在响应头中,一定要后端暴露给客户端即在
Access-Control-Expose-Headers
里列出来,否则即使服务器在协议回包里加了该字段,客户端也只能看到无法在代码中获取到它的值。
2.url下载(GET方式下载)
下载的文件存储在静态资源服务器中,可以使用这种方法。后端直接返回对应资源服务器的资源url,前端直接window.location.href方式获取即可。
window.location.href="http://www.域名/template.xlsx(文件名)";
window.open(url);
3.无API浏览器直接下载
将静态资源文件直接放于 public 目录下,打包时 public 文件不会被编译。
注意:静态资源的路径,在 public 文件夹下路径是/文件名
<a class="download-file" href="/file.xlsx" download="模板.xlsx">下载模板文件</a>
或者使用非 a 标签的按钮下载:
/*
@param {string} url 静态资源url
@param {string} filename 静态资源文件名(可选)
@param {string} target
*/
export const fileUrlHandled = ({ url, filename, target }) => {
const downloadElement = document.createElement('a')
downloadElement.style.display = 'none'
downloadElement.href = url
if (target) {
downloadElement.target = '_blank'
}
downloadElement.rel = 'noopener noreferrer'
if (filename) {
downloadElement.download = filename
}
document.body.appendChild(downloadElement)
downloadElement.click()
document.body.removeChild(downloadElement)
}
缺点:文件名不可控。
最后
以上三种文件下载方式,是工作中不同情境所用方法的总结,如果对你有所帮助的话,帮忙点赞呀👍,你的阅读和点赞是我继续下一篇的动力,感谢!
本文著作权归作者翻雪所有,转载请注明出处。