接口返回二进制文件流,前端通过blob对象实现下载

场景:项目中请求图片或者下载文件一般情况下都是接口返回url或者接口本身就是一个get请求访问接口直接下载。但是在某些情况下,接口会返回一个二进制文件流,在控制台打印或者network的preview中就是一串看不懂的字符串(下图)

第一次遇到的时候也是一脸迷茫,就顺着惯性思维总觉得接口返回的不对。但其实只是自己技术有限,没有接触到而已。这就是接口返回的文件的二进制流,通过js的Blob对象是可以转成文件下载下来的。

二进制流转图片:如果接口返回的是个图片,前端需求是展示这个图片,可以直接将api放到img标签的src中,和普通ajax请求的接口一样,这样在浏览器network中可以看到这个图片和请求一样,不过类型成了img类型的。

二进制流下载:借助blob对象,直接贴代码

      let xhr = new XMLHttpRequest()
      let fileName = 'file.docx' // 文件名称 
      xhr.open('GET', Api, true)
      xhr.responseType = 'arraybuffer'
      xhr.setRequestHeader(token, 'xxxxx') // 请求头中的验证信息等(如果有)
      xhr.onload = function() {
        if (this.status === 200) {
          let type = xhr.getResponseHeader('Content-Type')

          let blob = new Blob([this.response], {type: type})
          if (typeof window.navigator.msSaveBlob !== 'undefined') {
            /*
             * IE workaround for "HTML7007: One or more blob URLs were revoked by closing
             * the blob for which they were created. These URLs will no longer resolve as 
             * the data backing the URL has been freed." 
             */
            window.navigator.msSaveBlob(blob, fileName)
          } else {
            let URL = window.URL || window.webkitURL
            let objectUrl = URL.createObjectURL(blob)
            if (fileName) {
              var a = document.createElement('a')
              // safari doesn't support this yet
              if (typeof a.download === 'undefined') {
                window.location = objectUrl
              } else {
                a.href = objectUrl
                a.download = fileName
                document.body.appendChild(a)
                a.click()
                a.remove()
              }
            } else {
              window.location = objectUrl
            }
          }
        }
      }
      xhr.send()

09/12更新:

在接口做验证的时候,如果验证失败,接口返回json信息,但是由于设置了responseType='arraybuffer',这时候this.response将不再是json字符串,而是ArrayBuffer对象,要处理它来将后台返回的信息展示出来。

let uint8 = new Uint8Array(this.response) // 提取uint8Array
let resToString = decodeURIComponent(escape((String.fromCharCode(...uint8)))) // 解决乱码

得到的resToString就是后台返回的json字符串了。

只通过String.fromCharCode会出现中文乱码的情况

猜你喜欢

转载自blog.csdn.net/aydongzhiping/article/details/82462473