前端实现文件下载深度剖析

134 阅读2分钟

需求描述

在前后端分离开发的项目中,前端无论使用Vue或React哪种框架,发送HTTP请求都会使用Ajax异步请求的方式。在很多项目中都会选择使用 axios 发送请求。但是在使用 axios 实现下载功能时,往往会出现以下问题。

当前端直接使用 axios 去请求下载文件的 api 接口时,状态码返回200,但是获取的数据却是一堆乱码。

此时,你一定慌了,兄弟,抽根烟冷静下,继续往下看~

问题分析

下载其实是浏览器的内置事件,浏览器的 GET请求(iframe、a)、 POST请求(form)具有如下特点:

response 会交由浏览器处理;
response 内容可以为二进制文件、字符串等。
但是AJAX请求不一样:
response 会交由 Javascript 处理;
response 内容只能接收字符串才能继续处理。 因此,AJAX本身无法触发浏览器的下载功能。

解决方案

要在 axios 的 config 配置 responseType: ‘blob’ (非常关键),服务端读取文件,以 content-type: ‘application/octet-stream’ 的格式返回前端,前端接收到数据后使用 Blob 来接收数据,并且创建a标签进行下载。

一个对象的类型取决于 responseType 的值,当值为 “blob”时表示 response 是一个包含二进制数据的 Blob 对象。 在使用 axios 发起请求前,首先了解一下 responseType 这个属性是如何在 axios 中使用的。以 axios 最常用的 get 和 post 请求为例,这两种请求方式在传递参数的时候也是不同的: 在get请求当中,config 是第二个参数,而到了 post 里 config 变成了第三个参数,这是传递 responseType 第一个需要注意的地方。

最后结论

  1. 创建a链接标签
  2. 创建iframe
  3. 使用blob,采用window.URL.createObjectURL(blob)形式;

方法1和2适用于get请求,方法3适用于post请求,后端返回文件流