文件上传下载是项目中经常会遇到的常规功能,例如静态资源下载、数据导出等等。本文总结了三种针文件下载的方法。
前端实现下载的原理一般是基于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 = urlif (target) {downloadElement.target = '_blank'}downloadElement.rel = 'noopener noreferrer'if (filename) {downloadElement.download = filename}document.body.appendChild(downloadElement)downloadElement.click()document.body.removeChild(downloadElement)}
缺点:文件名不可控。
最后
以上三种文件下载方式,是工作中不同情境所用方法的总结,如果对你有所帮助的话,帮忙点赞呀👍,你的阅读和点赞是我继续下一篇的动力,感谢!
本文著作权归作者翻雪所有,转载请注明出处。

