Liudongge / Work-Notes

记录工作中遇到的问题和总结,便于之后归纳
1 stars 0 forks source link

文件下载问题总结 #45

Open Liudongge opened 5 years ago

Liudongge commented 5 years ago

1.下载文件重命名 优先使用fastdfs传参定义文件名的方式。若服务不支持,可以采用a标签filename属性来解决。

/**
 * 下载并重命名文件
 * @param {String} fileUrl 除去ip端口前缀的文件路径
 * @param {*} fileName 要设置的文件名称
 */
export function formatFileName(fileUrl, fileName) {
  getFile('/fileApi/' + fileUrl).then(function (blobContent) {
    const blob = new Blob([blobContent], {
      type: blobContent.type
    })
    const dom = document.createElement('a')
    dom.download = fileName
    dom.style.display = 'none'
    dom.href = URL.createObjectURL(blob)
    document.body.appendChild(dom)
    dom.click()
    document.body.removeChild(dom)
  })
}

这里使用了文件url直接发送ajax请求,responseType需设置为blob

2.文件下载接口返回值的处理 请求接口下载文件,在正常情况下返回文件流,异常情况下返回对应的异常信息。由于请求时设置了responseType,所以需要在response时做区分处理。

/**
 * 用于下载文件重命名的axios方法
 * @param {*} url 除去ip端口前缀的文件路径
 */
export function getFile(url) {
  return new Promise((resolve, reject) => {
    axios.get(url, {
      responseType: 'arraybuffer' // 使用arraybuffer获取文件流(优:较blob少一步转换为arraybuffer的处理)
      // responseType: 'blob' // 如果使用blob,则对返回值需做转换为arraybuffer的处理
    })
      .then(response => {
        if (response.status === 200) {
          // 如果返回类型是json,代表出现异常。将blob对象转成json对象
          if (response.headers['content-type'].includes('application/json')) {
            // 如果使用的是blob返回类型,则需要先转换为arraybuffer再转成json对象
            // const reader = new FileReader()
            // reader.addEventListener('loadend', function () {
            //   // reader.result 包含转化为类型数组的blob
            //   const decoder = new TextDecoder('utf-8')
            //   const resJson = JSON.parse(decoder.decode(new Uint8Array(reader.result))) // 转化成json对象
            //   resolve(resJson)
            // })
            // reader.readAsArrayBuffer(response.data)
            const decoder = new TextDecoder('utf-8')
            const resJson = JSON.parse(decoder.decode(new Uint8Array(response.data))) // 转化成json对象
            resolve(resJson)
          } else {
            resolve(response.data)
          }
        } else {
          Message.error(response.message || '文件下载服务异常,请联系客服')
        }
      }, err => {
        reject(err)
      })
      .catch(error => {
        reject(error)
      })
  })
}

同时,需要在调用处区分处理。

/**
 * 导出excel文件
 * @param {String} url 接口地址
 * @param {*} fileName 下载的文件名称
 */
export function exportExcel(url, fileName) {
  getFile(url).then(data => {
    if (toString.call(data) === '[object ArrayBuffer]') {
      const blob = new Blob([data], {
        type: data.type
      })
      const dom = document.createElement('a')
      dom.download = fileName
      dom.style.display = 'none'
      dom.href = URL.createObjectURL(blob)
      document.body.appendChild(dom)
      dom.click()
      document.body.removeChild(dom)
    } else if (toString.call(data) === '[object Object]') {
      Message.error(data.message || '文件下载失败')
    } else {
      Message.error('文件下载服务处理异常')
    }
  })
}

以上代码在catch到异常时的处理待完善