关于前端实现点击链接直接下载而不会跳转新页面的问题

781 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情
最近碰到一个问题,需求是点击链接直接就会下载文件,而不是跳到新页面预览文件,但是实现过程中发现了一些问题,就在此记录下来,希望能帮到同样被这个问题困扰的掘友们!

基本函数实现

async downFile(val, key) {
    const params = {
        key,
        prodId: val.prod.id
    }
    //hide方法是为了增加用户体验的
    let hide = this.message.loading("文件下载中", 0)
    const res = await getDownLoadUrl(params)
    const { code, result, message } = res
    if(code === 200 && result.url) {
        const ele = document.createElement('a')
        ele.setAttribute('href', result.url)
        ele.setAttribute('download', result.appendix_name)
        ele.setAttribute('target', '_blank')
        ele.click()
        setTimeout(()=>{
            hide()
            this.$message.success(`${result.appendix_name}下载成功!`, 1000)
        })
    } else {
        let mess = message
        if(!message) {
            mess = '下载失败!'
        }
        hide()
        this.$message.error(mess)
    }
}

这里首先要对已经忘记了原生JavaScript的掘友们,回顾一下我们刚学JavaScript的时候用的一些属性方法了:

  • document对象:我们如果想要操作页面上的某部分,肯定需要先获取到该部分对应的元素,才能进行后续操作对吧。
  • createElement:当页面中没有想要的元素,就需要自己创造一个了,createElement()方法可以创建元素节点,返回一个 Element 对象。
  • setAttribute:既然元素有了,那么就需要给它设置属性了,setAttribute()方法可以给某个元素设置属性,并为其赋值,不论该元素是原有的还是createElement创造的。
  • click:点击事件,上述代码中是直接调用ele对象的点击事件,即点击a标签。
    问题在于,这种方法对img、PDF等格式的文件无效,当文件是这些格式时,浏览器默认会打开新页面预览而不会下载。

axios+blob的方法

经过多次尝试,发现了用axios发请求,并结合blob的方法,可以解决这个问题。 axios是一个发送请求和操作请求的轻量级库,大家都知道,就不用多加赘述了。关于blob,它是二进制类型大对象,表示用来存储二进制数据,在我们前端通常用于文件上传,图片预览等等。在 JavaScript 中 Blob 对象表示一个不可变、原始数据的类文件对象,它不一定非得是大量数据,也可以表示一个小型文件的内容。
我们使用构造函数new Blob方法来创建一个blob对象,使用 URL.createObjectURL方法来创建 Blob URL,该方法接收一个 blob 对象,并为其创建一个唯一的 URL。代码如下:

downFile() {
      const config = {}
      // 这一步可能很关键,特别是在能下载,但是下载下来打开异常的时候。
      config.responseType = 'blob'
      axios
        .get(
          'https://img1.baidu.com/it/u=375194120,1211299301&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500',
          config
        )
        .then((res) => {
          const blob = new Blob([res.data]) // 将字节流(字符流)转换为 blob 对象
          let url = window.URL.createObjectURL(blob)
          //  解决 ie 不支持下载 blob资源
          if ('msSaveOrOpenBlob' in navigator) {
            window.navigator.msSaveOrOpenBlob(blob, 'ceshi.jpg')
            return
          }
          let ele = document.createElement('a')
          ele.style.display = 'none'
          ele.href = url
          ele.download = 'ceshi.jpg'
          document.body.appendChild(ele)
          ele.click()
          document.body.removeChild(ele) // 下载完成移除元素
          window.URL.revokeObjectURL(url) // 释放掉blob对象
        })
    },

end

以上就是我的一点小小的分享,希望能对你有所帮助,感谢!