从window.URL.createObjectURL简介到下载文件的通用方法

使用场景: 在导出文件或下载文件的时候,有时候会返回blob文件流的数据,而不是返回URL地址,对于这种场景,下面谈谈其应用。

1. 简析window.URL.createObjectURL方法:

创建一个新的对象URL,该对象URL可以代表某一个指定的file对象或者bold对象。

用途: 可以用于在浏览器上预览本地的图片或者视频。

URL对象是硬盘(SD卡等)指向的一个文件路径,如果我们做文件上传的时候,想在没有上传服务器端的情况下看到上传图片的效果图的时候,就可以通过var url = window.URL.createObjectURL(files[0]);获得一个http格式的url路径,这个时候就可以设置img中的src进行显示了。

2. 关于blob的一点说明

new Blob 就是Blob对象是二进制数据,但它是类似文件对象的二进制数据,因此可以像操作File对象一样操作Blob对象,实际上,File继承自Blob。

3. 封装一个通用的导出或下载方法( 包含错误信息处理)

export default function downloadFile(res, fileName, fileType = '.xls', target = '_self') {
      const blob = new Blob([res], {type: 'application/json'})
      // 通过fileReader读取这个blob
      const reader = new FileReader()
      // 将blob对象以文本的方式读出,读出完成后将会执行onload方法
      reader.readAsText(blob)
      reader.onload = e => {
        const textRes = e.target.result
        // 此处对fileReader读出的结果进行JSON解析
        // 可能会出现错误,需要进行捕获
        try {
          const json = JSON.parse(textRes)
          if (json) {
            // 解析成功说明后端导出出错,进行导出失败的操作 例如展示后端返回的失败提示
            alert(json.errMsg)
            return
          }
        } catch (err) {
          // 该异常无法将字符串转为json
          // 说明返回数据是一个流文件
          // 不需要处理该异常
        }
        
        // 如果代码能够执行到这里,说明后端给的是一个流文件
        // 这里可以获取header中的cotent-type设置对应的type即可下载不同类型的文件
        let blob = new Blob([res], {type: 'application/ms-excel'}) // excel
        // 兼容IE & Edge
        if (window.navigator && window.navigator.msSaveOrOpenBlob) {
          navigator.msSaveOrOpenBlob(blob,fileName)
        } else {
          // 兼容不同浏览器的URL对象
          const url = window.URL || window.webkitURL || window.moxURL
          // 创建下载链接
          const downloadHref = url.createObjectURL(blob)
          // 创建a标签并为其添加属性
          let link = document.createElement('a')
          link.href = downloadHref
          link.target = target
          link.style.display = 'none'
          link.setAttribute('download', fileName + fileType)
          
          // 触发点击事件执行下载
          // 火狐浏览器上a标签点击导出无效。解决办法:需要先将a标签添加到当前页面上,在执行click,之后再移除该节点,而不能直接执行click
          document.body.appendChild(link)
          link.click();
          // 下载完成进行释放
          url.revokeObjectURL(donwnloadLink.href)
          document.body.removeChild(link);
        }
      }
    }
    

注意: 如果这种方法存在乱码的情况,可以在你的接口方法里写上 responseType: 'arraybuffer’或者'blob'
    export function export(params){
     return request({
         url: '/api/exportFile',
         method: 'POST',
         data:params,
         responseType: 'blob'
         //  responseType: 'arraybuffer’ 
     })
}

4. 关于responseType 属性的一点拓展

XMLHttpRequest.responseType 属性是一个枚举类型的属性,返回响应数据的类型。它允许我们手动的设置返回数据的类型。如果我们将它设置为一个空字符串,它将使用默认的"text"类型。

具体属性值类型可查阅: XMLHttpRequest.responseType - Web API 接口参考 | MDN

参考文档: 下载各类文件流的方法(兼容各个浏览器,包含错误信息处理)_STRIVE_LC的博客-CSDN博客_下载 文件流

你可能感兴趣的:(服务器,前端,javascript)