文件下载

327 阅读2分钟

下载.gif

日常工作中我们经常遇到文件下载的需求, 模板下载、 附件下载、 配套工具下载等等, 针对这些场景我总结了几个下载方案分享给大家

方案一

使用我们最常见的 a 标签

<a href="https://nodejs.org/dist/v18.15.0/node-v18.15.0-x64.msi" download=''>下载Node.js</a>

最终效果就像这样: 下载 Node.js

方案二

自己封装 Ajax , 为什么需要这种方案呢, 因为有时候接口是需要鉴权的, a 标签是无法添加 token 之类的

//封装下载公用函数,  提供传文件名、后端接口
function downloadFileHttp(fileName, url) {
    const XHR = new XMLHttpRequest()
    const BASEURL = window.AppConfig.baseUrl //项目配置全局的请求url, 大同小异

    XHR.open('get', BASEURL + url)
    //设置请求头信息
    XHR.setRequestHeader('X-Token', getCookie('app-token'))
    XHR.responseType = 'blob'
    XHR.onload = function() {
       if (this.status == 200) {
          let blob = this.response
          if (window.navigator.msSaveOrOpenBlob) { //这个判断主要用来兼容浏览器
             navigator.msSaveBlob(blob)
          } else {
              //像谷歌可以不需要这个判断, 直接用下面这段
             let tagA = document.createElement('a')
             tagA.href = createObjectURL(blob)
             tagA.download = filename
             tagA.style.display = "none"
             tagA.click()  //做模拟点击下载
          }
       }
    }
    XHR.send()
}

然后页面需要用的时候引入调用即可

//demo.vue
<template>
    <button @click="handleDown">下载附件</button>
</template>

import downloadFileHttp from './utils'
export default {
    methods: {
       handleDown() {
           downloadFileHttp('部署流程整理', '/deploy/template/download')
       }
    }
}

下载2.gif

方案三

有些同学就要问了:有了前两种方案,还需要第三种方案吗?
答案是要的, 这时候来了个需求: 接口要请求体传参, 很明显上面那种方法get只支持 query 传参(拼接在接口后面) XHR.send(params) 只支持post哈。

那又有人问了为什么会有这种需求呢? 我想到的是可能出于 安全 又或者出于 美观 考虑, 我们就不想拼接在请求链接里, 这时候方案二就无法满足了, 这时候我们可以利用 axios

//demo.vue
<template>
    <button @click="handleDown">下载附件</button>
</template>

import axios from 'axios'
export default {
    methods: {
       handleDown( file ) {
           axios({
                url: '/person/template/download',
                method: 'get',
                headers: {
                    'X-Token': getCookie('app-token'),
                },
                responseType: 'blob',
                params: {
                    filePath: file.path,
                    fileSize: '100M',
                    ...
                    //这里可以传一大堆你想要的
                }
            }).then(res => {
                if (res.status === 200) {
                    let a = document.createElement('a')
                    a.href = window.URL.createObjectURL(res.data)
                    a.download = file.name
                    a.style.display = 'none'
                    a.click()
                }
            })
       }
    }
}