1、前提
这几天项目开发,有个需求点是有两个按钮点击事件,点击时分别需要下载和导出excel文件,两个都是GET接口请求方式,不过区别是:
- 一个是后端直接给接口地址,前端
不用传参数给后端,后端直接返回一个excel文件(这种是文件上传到资源服务器上,后端只保存了文件地址,前端拿到后端返回的文件地址直接下载) - 一个是后端给了接口地址,同时前端需要给后端
传一些参数字段,后端返回的不是一个excel文件,而是返回二进制流,需要前端自己转换(这种是文件就存在后端服务器上(通常是临时根据前端参数动态生成,用完就删除),后端读取文件后向前端返回文件的二进制流)
2、通过文件地址下载(直接下载excel文件)
我们现在文件夹download下面创建一个service文件夹(模拟服务端),里面有一个.xlsx文件;然后在download文件夹下面创建一个index.html(模拟前端)如图所示

我们可以安装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>

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

- 这种下载相当于一个
get请求,浏览器直接访问该静态资源地址,download属性告诉浏览器这个a标签不是打开页面预览而是进行下载。 - 不过我们发现,我们在download设置的文件名,并没有生效,这个后面讲
2.2、window.open()
excel文件路径保持不变,我们换成window.open的方式,将文件路径作为window.open的第一个参数,_self作为第二个参数


- 可以看出,window.open也可以下载成功
2.3、实例
在某项目中,我找了一个相关的下载案例,该接口是后端只提供了接口地址,即后端保存了文件地址,前端直接调用后端接口地址,不用向后端传参数,拿到后端返回的文件直接下载。
下图是接口文档:

下图是项目中相关代码:

- 已做测试,方法一和方法二都可以,不过从代码简介程度,
window.open(url,'参数二')看起来更加简介
3、二进制流文件下载(需要进行转换)
这种情况一般就是实际项目使用的ajax请求接口方式,前端传递若干参数,后端返回文件二进制流。前端需要将二进制转换成一个可以下载的文件地址。
3.1、二进制转url + <a>标签
我们在刚才download文件夹下面使用create-react-app创建一个新的my-app文件夹。并对入口的App.js文件页面进行修改;
同时service文件夹下面创建一个service.js模拟的下载接口。

npm install -g create-react-app
npx create-react-app my-app
cd my-app
然后安装axios
npm install -g axios
按钮页面:

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

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

(sudo) npm run start

- 我们发现,请求得到的返回的结果全是乱码
- 其实根本原理跟上面普通下载一样,都是
通过一个文件的地址去下载,不过现在是二进制数据,所以现在关键就是现在把这些二进制数据生成一个文件url。
首先设置axios配置项返回结果改成二进制格式。
axios({
method: 'get',
url: "http://localhost:8001/download",
data: { } ,
responseType: "arraybuffer" // arraybuffer是js中提供处理二进制的接口
})
这时我们再次点击按钮

- 发现
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()
})
按钮页面整体:

这时我们再次点击按钮

- excel文件可以成功下载,此时的
二进制流也被我们转成了url的形式,并作为<a>标签的href属性值
3.2、实例
在某项目中,我找了一个相关的下载案例,该接口是后端不仅提供了接口地址,而且需要前端传递某些参数。通常这种文件是存在后端服务器上(通常是临时根据前端参数动态生成,用完就删除),后端读取文件后向前端返回文件的二进制流。前端需要将这些二进制流数据转成一个url地址,再进行下载。
下图是接口文档:

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


本文介绍了前端如何处理两种不同的Excel下载方式:一种是通过后端提供的文件地址直接下载,另一种是接收后端返回的二进制流并转换为可下载的文件。通过HTML的<a>标签、window.open()方法以及axios处理二进制流展示了具体的实现步骤,并给出了实际项目中的代码示例。

428

被折叠的 条评论
为什么被折叠?



