• 前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案


    场景还原

    我在前端使用axios接收后端xlsx表格文件流并下载,xlsx文件能够下载成功,但是打开却显示文件无法打开
    xlsx文件无法打开

    相关代码

    请求API封装:Content–Type以及responseType经核对均没有问题

    export function downloadStudent(courseId, data) {
      return request({
        url: `/curriculum/course/download/${courseId}`,
        method: 'POST',
        data,
         headers: {
          'Content-Type': "application/json"
        }, 
        responseType: 'blob'
      })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    接口调用:
    在这里插入图片描述

    下载函数封装:

    /**
     * 下载处理器
     * @param name 文件名称
     * @param data 数据
     */
    export const handleDownload = (name, data) => {
      const fileUrl = window.URL.createObjectURL(new Blob([data]))
      const a = document.createElement('a')
      a.style.display = 'none'
      a.href = fileUrl
      a.setAttribute('download', name)
      document.body.appendChild(a)
      a.click()
      window.URL.revokeObjectURL(a.href)
      document.body.removeChild(a)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    开发者工具 - 网络请求记录

    预览:二进制数据
    在这里插入图片描述

    问题排查

    定位

    可以看到文件数据已经接收到并且是二进制的,但是转为的xlsx文件却无法打开,所以我打印了一下数据想看下数据是否有问题
    在这里插入图片描述
    然后两眼一黑, undefined
    在这里插入图片描述
    这意味着我解构拿出来的data是未定义的,也就是说,在axios封装时候,响应拦截器里我经过一一系列处理,最后在code==200时会抛出resolve(response.data),我与后端约定的这个响应数据的格式是这样:

    {
    	"code": 200,
    	"data": xxxx,
    	"success": "success",
    	"success": true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    那么解构出来显示data undefined,就意味着这个接收文件流的接口返回的响应数据格式很可能不是上面的格式。需要看一看response.data

    改bug

    既然解构拿出来没有那就不解构了,去响应拦截器里打印原始response看看
    在这里插入图片描述
    type是Blob没有问题,但是从response可以看到,data格式变了,response.data已经是解析后的Blob对象, 里面自然没有我们想要解构拿到的data,所以在最开始的接口API调用里不可以解构拿data,直接拿响应拦截器里resolve出的response.data用就行

    在这里插入图片描述
    在这里插入图片描述
    现在下载的xlsx文件已经可以正常打开了
    在这里插入图片描述

    总结

    是一次粗心大意,习惯性地直接解构拿出需要的数据,但忽略了接口文档里这个接口的响应示例说明(虽然说这个接口的响应示例说明里也啥都没写,但相比其他的接口,确实啥都没写也算是一种特别说明)

    所以,更高效的解决方式就是 -->

    去看文档

  • 相关阅读:
    计算机专业数学蒙题技巧
    C语言等长编码压缩和哈夫曼编码压缩
    springboot+elk日志
    Spring5应用之Cglib动态代理
    实际上手体验maven面对冲突Jar包的加载规则
    微信小程序前后端交互与WXS的应用
    基于EMR的新一代数据湖存储加速技术详解
    pycharm联合Anaconda
    【代码执行以及调试】
    自动控制原理4.2---根轨迹绘制的基本法则
  • 原文地址:https://blog.csdn.net/liushi21/article/details/134216566