VUE 文件下载,流形式的文件下载,判断返回的是流还是JSON;获取下载名称

发布于:2025-05-23 ⋅ 阅读:(22) ⋅ 点赞:(0)

        在前端中,有很多下载文件的情况,在大多数情况下,后端是以流的形式把需要的数据返回给前端,这就有接口报错的情况在里面,如果接口报错,有的后端则会返回一个带有错误信息的JSON给我们,比如下面这样:

{
  code: "-1",
  data: null,
  message:"没有数据导出!"
}

所以我们在封装axios的时候,需要在请求拦截中做一些处理:

service.interceptors.response.use((response) => {
  if (response.config.responseType === 'blob') {
    const contentType = response.headers['content-type']
    // 情况1:收到的是文件流(正常下载)
    if (contentType.includes('excel')) {
      // 方式 1:从自定义头获取
      const filenameFromHeader = response.headers['filename'];

      // 方式 2:从 Content-Disposition 解析
      const contentDisposition = response.headers['content-disposition'];
      const filenameFromCD = contentDisposition?.split('filename=')[1]?.replace(/"/g, '');
      return {
        blob: response.data, // 二进制数据
        filename: decodeURIComponent(
          filenameFromHeader || filenameFromCD // 从header获取文件名
        )
      }
    }

    // 情况2:收到的是错误信息(需要转换)
    return new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.onload = () => {
        try {
          const json = JSON.parse(reader.result)
          if (json.status !== 200) { // 根据你的错误码约定调整
            reject(json.message || '下载失败')
          }
        }
        catch (e) {
          console.log('e==>', e);
          reject('响应解析失败')
        }
      }
      reader.readAsText(response.data)
    })
  }
  return response.data
}, err)

当然,在封装我们的下载方法的时候,也要记得给responseType加上blob

export function functionName(parameter) {
  return axios({
    url: '/api/XiaZaiDiZhi',
    method: 'post',
    data: parameter,
    responseType: 'blob'
  })
}

在调用方法的时候,如果接口报错,返回了JSON,我们就可以直接在catch中获取到报错信息,也可以获取到我们所需要的文件名称

//调用接口
functionName(fromsData)
          .then((data) => {
            const fileName = data.filename;
            const url = window.URL.createObjectURL(data.blob);
            const a = document.createElement("a");
            a.href = url;
            a.download = fileName;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
          })
          .catch((err) => {
            this.$message.error(err);
          });


网站公告

今日签到

点亮在社区的每一天
去签到