1、前提

这几天项目开发,有个需求点是有两个按钮点击事件,点击时分别需要下载和导出excel文件,两个都是GET接口请求方式,不过区别是:

  • 一个是后端直接给接口地址,前端不用传参数给后端,后端直接返回一个excel文件(这种是文件上传到资源服务器上,后端只保存了文件地址,前端拿到后端返回的文件地址直接下载)
  • 一个是后端给了接口地址,同时前端需要给后端传一些参数字段,后端返回的不是一个excel文件,而是返回二进制流,需要前端自己转换(这种是文件就存在后端服务器上(通常是临时根据前端参数动态生成,用完就删除),后端读取文件后向前端返回文件的二进制流)

2、通过文件地址下载(直接下载excel文件)

我们现在文件夹download下面创建一个service文件夹(模拟服务端),里面有一个.xlsx文件;然后在download文件夹下面创建一个index.html(模拟前端)如图所示

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_二进制流


我们可以安装serve,用来启动静态资源服务器

npm install -g serve

安装完后之后,进入service目录,并启动服务

cd service 
serve -s

注意:要先进入service目录,在启动服务

这时excel文件的路径为http://localhost:5000/excel文档.xlsx

2.1、<a>标签download

我们先使用<a>标签的方式,href属性中写上文件的路径(可以看成后端给你的文件接口地址),并写上download属性(写上这个属性,才代表可以下载)

注意:download这个属性是H5新增的,之前是没有的。

<a href="http://localhost:5000/excel文档.xlsx" download='测试的excel文件'>下载excel文件</a>

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_a标签_02


我们打开index.html页面点击a链接,进行下载

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_node.js_03

  • 这种下载相当于一个get请求,浏览器直接访问该静态资源地址,download属性告诉浏览器这个a标签不是打开页面预览而是进行下载
  • 不过我们发现,我们在download设置的文件名,并没有生效,这个后面讲
2.2、window.open()

excel文件路径保持不变,我们换成window.open的方式,将文件路径作为window.open的第一个参数_self作为第二个参数

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_node.js_04


前端传过来的二进制文件流python怎么解析 前端下载二进制文件_node.js_05

  • 可以看出,window.open也可以下载成功
2.3、实例

在某项目中,我找了一个相关的下载案例,该接口是后端只提供了接口地址,即后端保存了文件地址,前端直接调用后端接口地址,不用向后端传参数,拿到后端返回的文件直接下载。

下图是接口文档:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_文件地址_06


下图是项目中相关代码:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_javascript_07

  • 已做测试,方法一和方法二都可以,不过从代码简介程度,window.open(url,'参数二')看起来更加简介

3、二进制流文件下载(需要进行转换)

这种情况一般就是实际项目使用的ajax请求接口方式,前端传递若干参数,后端返回文件二进制流。前端需要将二进制转换成一个可以下载的文件地址

3.1、二进制转url + <a>标签

我们在刚才download文件夹下面使用create-react-app创建一个新的my-app文件夹。并对入口的App.js文件页面进行修改;

同时service文件夹下面创建一个service.js模拟的下载接口。

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_a标签_08

npm install -g create-react-app

npx create-react-app my-app

cd my-app

然后安装axios

npm install -g axios

按钮页面:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_javascript_09

  • 我们将App.js入口页面改为一个下载的按钮,并对按钮增加点击动作

接口service.js:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_文件地址_10


在service目录下新开一个终端窗口,启动后端服务:

node service.js

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_javascript_11

(sudo) npm run start

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_javascript_12

  • 我们发现,请求得到的返回的结果全是乱码
  • 其实根本原理跟上面普通下载一样,都是通过一个文件的地址去下载,不过现在是二进制数据,所以现在关键就是现在把这些二进制数据生成一个文件url

首先设置axios配置项返回结果改成二进制格式

axios({  
  method: 'get',    
  url: "http://localhost:8001/download",    
  data: { } ,
  responseType: "arraybuffer" // arraybuffer是js中提供处理二进制的接口
})

这时我们再次点击按钮

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_二进制流_13

  • 发现response.data已经不是乱码格式,而是一个Blob类型数据(Blob数据是以随机存取块(binary large object)的形式存储任何种类的二进制数据
  • 将这些二进制数据生成一个文件url,用URL.createObjectURL生成url时需要传入Blob类型的参数
  • 生成了url后,就是模拟a标签的方式来下载
}).then(response => {      
      console.log('---response----',response.data)  
      
      let blob = new Blob([response.data], {            
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 
      }) // 针对excel文件         
      console.log('---blob---',blob)
      
      // 通过URL.createObjectURL生成文件路径          
      let url = window.URL.createObjectURL(blob)          
    
      // 创建a标签          
      let ele = document.createElement("a")          
      ele.style.display = 'none'          
    
      // 设置href属性为文件路径,download属性可以设置文件名称          
      ele.href = url          
      ele.download = "测试文件"          
    
      // 将a标签添加到页面并模拟点击          
      document.querySelectorAll("body")[0].appendChild(ele)          
      ele.click()   

      // 移除a标签          
      ele.remove()    
 })

按钮页面整体:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_文件地址_14


这时我们再次点击按钮

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_node.js_15

  • excel文件可以成功下载,此时的二进制流也被我们转成了url的形式,并作为<a>标签的href属性值
3.2、实例

在某项目中,我找了一个相关的下载案例,该接口是后端不仅提供了接口地址,而且需要前端传递某些参数。通常这种文件是存在后端服务器上(通常是临时根据前端参数动态生成,用完就删除),后端读取文件后向前端返回文件的二进制流。前端需要这些二进制流数据转成一个url地址再进行下载

下图是接口文档:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_javascript_16


下图是项目中的相关代码:

前端传过来的二进制文件流python怎么解析 前端下载二进制文件_a标签_17