
故事还得从一个朴实无华的需求说起,产品要求在移动端 H5 应用中增加导出 excel 的功能,年底前要上线的,我一想导出excel
,这我不是在 PC 端写过 N 次了嘛,简直小菜一碟嘛。我就是加班,也不要后端开一个接口(开个玩笑 O(∩_∩)O 哈哈~)。
后端大佬给出的接口是这样的:
路径: /api/project/statistics/excelProject
请求类型: Get
请求头: Content-Type:application/x-www-form-urlencoded
需要的参数: beginDate
endDate
keyword
我一看这个接口,既然是 get 请求,那么将参数拼接在地址后面,岂不是可以直接通过 window.open 来打开新窗口触发 get 请求下载文件了。于是就有了第一种方法:
1 |
|
很快啊,一下子就在 PC 端上的浏览器实现了导出 excel 的功能,不多不少,功能刚刚好,这导出 excel 多是一件美事呀。
乍一看还真简单呢!然后我准备在移动端上进行测试,结果呢,拉了。。。
首先是安卓微信浏览器
,使用 window.open 会直接打开一个新窗口,然而这个新窗口并不是微信浏览器里的,而是在手机上默认的浏览器打开。那么问题来了,用户并没有在手机默认浏览器登录过,然后触发导出接口必然会对用户权限进行验证所以就如下所示了:
既然安卓系统上的微信浏览器无法实现,那么可以试试手机默认的浏览器
呀(这里我用的是小米)毕竟打开新窗口时用户的权限信息都是在的呀。然后,我又进行了测试。结果如下所示,
虽然有了下载的弹框,但是下载居然是 bin 文件。我百思不得姐,于是又去冲了会浪,综合网上的说法,我断定是接口响应头部 content-type 类型不对才导致的问题。于是,我用抓包工具看下了这个接口的响应。你们有人可能会好奇,在 PC 端的 chrome 中的 network 不是可以直接看接口的请求记录嘛。当然我也想这么操作呀,只不过当我触发 window.open 时,浏览器貌似闪了一下就弹了个下载提示框就没了,请求记录压根没有在原来窗口的 network 中记录下来。所以我只能请出抓包工具了呀。然后一看抓包截图就发现了:
这里居然用的是
1 |
|
于是我让后端将响应头部改成了这样之后,才算在安卓上的浏览器能正常下载 excel
1 |
|
中途后端也曾用过’application/vnd.ms-excel’,但是兼容效果并不理想,虽然在安卓机的浏览器上确实能正确弹出下载 excel 文件的提示,但是在 ios 浏览器中压根连 excel 都无法预览了,更别提弹框提示下载了。
前面介绍的都是安卓机的试验,那现在看看 ios 上的表现,首先试试ios微信浏览器
呢?这里就挺神奇的,我本以为会同安卓一样打开了默认浏览器 Safari,但是在触发 window.open()时,并没有在手机默认的 safari 浏览器中打开新窗口而是在微信浏览器内部打开了新窗口,那么此时用户的权限便是正常的。我一想,这不就代表会进行下载了嘛!!!然后离谱的事情发生了,新窗口只是中正确展示了 excel 文件信息,但是并没有下载提示(貌似只有用户在第一次进行下载时,才会有下载提示)
之后,我又在 ios 默认浏览器 Safari 上进行了测试,测试结果和ios微信浏览器
的运行效果是一样的:同样只是在新窗口中展示了 excel 文件却并没有下载的提示框。
因此我得出结论:window.open是没法完整实现安卓和ios各自的微信浏览器以及手机默认浏览器下载excel的功能,综合表现很差
。
既然 window.open 走不通,那么我准备用 a 标签来试试。
由于后端给出的接口是 get 请求。所以我可以尝试两种方式来进行 a 标签的下载文件。
一种便是将 get 请求返回的文件流转成 url;另一种就是直接使用 get 请求地址。代码分别如下:
1 |
|
这种方法在 ios 微信浏览器和安卓微信浏览器中的效果一样,点击之后只是进行了接口请求,虽然也生成了 a 标签但是点击后并不能导出 excel。
然而在部分移动端浏览器中可以实现比如 Safari、小米浏览器等可以正常提示下载并导出 excel。
1 |
|
使用绝对地址的方法的话,ios 微信浏览器只会在新页面中展示 excel,但没有提示下载。但在安卓微信浏览器中触发方法时,会在手机默认浏览器打开新窗口,那么会因为没有用户登录信息而提示未登录就跟 window.open 产生的结果是一样的。
在测试 iOS 默认浏览器 Safari 中可以正常展示且提示了下载,安卓手机默认浏览器(小米)可以正常提示下载。
总结 a 标签的各种浏览器测试结果:文件流转URL比直接使用地址的表现差,a标签下载excel在手机默认浏览器中有很好的表现,但是在微信浏览器中依然无法实现下载功能。综合表现比通过window.open更好些。
本来是想实现在微信浏览器中实现直接下载 excel 的功能,但是经过多次实验之后,发现微信浏览器确实在下载文件方面确实表现不够好。因此最后和同事讨论的解决办法是:使用a标签进行下载excel,判断用户登录的浏览器是否是微信浏览器,是的情况下,我们给出提示:通过点击右上角(···)并在浏览器(默认)中打开。而用户一开始就是在默认浏览器打开时,我们就不做任何处理。