H5 微信公众号打开pdf文件的思考

0. 背景

最近遇到一个需求是H5通过微信公众号打开一个pdf链接(url形式,浏览器输入url可直接下载)看上去很简单,不过还是有不少要注意的。

1. 如何打开文件

拿到需求第一想法,怎么打开链接呢?window.open? window.location.href? 方法还是挺多的。MDN回顾.

window.open:指定名字将相关资源加载在浏览器新窗口上。

//  pdfUrl:要加载的资源,strWindowName,可选,窗口名称。
let windowObjectReference = window.open(pdfUrl, strWindowName);

我这里只需要填写pdfUrl即可,当然跟打开新网页的效果不同。在pc端实现的效果是直接下载pdf。

但是,但是,第一次做移动端,才涨知识了,苹果端可以直接显示弹窗并下载,安卓端就会出现如下信息:
安卓端window.open报错网上的说法挺多的,也有说在安卓微信公众号可以使用window.open,有说不行的。但我查到的是说以前微信公众号很多不良商家通过window.open打开非法页面,用户体验不好,所以如果通过window.open开启组织弹出窗口的政策(见上图)。然后试了window.location.href

window.location: 只读对象,返回location对象,包含有关文档当前位置的信息

// 两者等价
window.location.href = 'www.baidu.com';
window.location = 'www.baidu.com'; 

不过这里也有坑(我后来发现可能是pdfUrl的原因还好,还是要注意!),如安卓用window.location.href从微信浏览器跳转原生浏览器无效,查阅网络发现可能是缓存的问题,加上时间戳来刷新缓存。

window.location.href = url + '?time='+((new Date()).getTime());

和领导沟通后,安卓机这块需求变成:微信公众号内,点击“下载”后显示弹窗,引导用户从默认浏览器打开再下载pdf。这里就需要判断用户所处于什么浏览器了(微信内置浏览器/手机原生浏览器)。

2. 适配不同端

判断用户浏览器处于什么环境,JS提供了一个很强大的API: navigator.userAgent

navigator.userAgent: 返回用户现在浏览器的用户代理

以我自己windows端Chrome浏览器为例子

console.log(navigator.userAgent);
// Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36

这样就好说了,通过indexOf,match都可以判断浏览器环境,

// 判断是否移动端
// /i不区分大小写模式
const isMobile = /Mobi|Android|iPhone/i.test(u);
//判断是否是安卓
const isAndroid = navigator.userAgent.indexOf('Android') > -1 || navigator.userAgent.indexOf('Linux') > -1;
//判断是否是ios
const isIOS = !!navigator.userAgent.match(/\(i[^;]+;(U;)? CPU.+Mac OS X/));
// 判断是否是微信
const isWeixin = navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1;

判断浏览器所处环境可参考此网站:根据UserAgent判断浏览器类型

不过,这个地方有个问题需要注意(MDN上提出:Navigator.userAgent)
这种方式要浏览器提供了尽可能少的信息。不要假设此浏览器这个属性的值在未来版本有相同的值。
如我的安卓手机默认浏览器用这个方法就是ios端(??),不过大部分都可以通过判断进行下载就好,不然测试成本太高了。

所以,领导给我的需求(见标题2)就变成了:
(1)判断是否是移动端,是进(2),不是直接window.location.href下载pdf(后来跟老师聊其实这步可以不要,毕竟是移动端的组,但以防万一还是判断下
(2)判断是安卓还是苹果,是进(3),不是直接window.location.href下载pdf
(3)判断是在微信内置浏览器还是手机原生浏览器,是微信先显示弹窗,告诉用户点右上角…通过浏览器重新进入该页面下载,如果不是微信浏览器,不显示弹窗直接下载
在这里插入图片描述

3. iOS端下载文件名null

在产品测试的时候,发现iOS点击下载后会出现一个情况,window.open(url)有这个问题。
在这里插入图片描述
查阅资料看到一个微信公众号官方人员的回答,应该是相关的:

这里弹窗时还没有真正开始下载,显示的文件名依赖请求response header中Content-Disposition的filename,你没有填这个字段,所以拿到的是空的。后面真正开始下载客户端才能拿到文件名
来源: 微信内置浏览器下载pdf标题null

但领导意思是,虽然后端Content-Disposition没有填写,但尽量不让数据提供方改接口内容(毕竟要磕头)。最后他给了一种解决方法。

// 创建XHR对象
const x = new window.XMLHttpRequest();
// 发送XHR请求
x.open('GET', url, true);
// 返回文件类型
x.responseType = 'blob';
x.onload = () => {
  const url = window.URL.createObjectURL(x.response);
  const a = document.createElement('a');
  a.href = url;
  a.download = '123345.pdf';
  a.click();
};
x.send();

一点点啃:

XMLHttpRequest(XHR):此对象与服务器交互,在XMLHttpRequest可在不刷新页面时请求特定URL,获取数据。AJAX编程中使用
open(): 规定请求方法,请求url,是否异步请求
send(): 请求发到服务器

这样重新发送了请求在ios进行pdf下载进行文件下载时文件名null的问题。

4. 其他
  1. vconsole查看接口情况,存储信息。当确定要传生产环境了记得注释掉
import VConsole from 'vconsole';
const vConsole = new VConsole();
  1. 不同页面数据传值的方法:
  • vuex(复杂)
  • localStorage(不同页面存储内容不相互独立)
  • sessionStorage(关页面就没了)
  • cookie(不安全,存储数据少)
  • 路由传参
    当微信内置浏览器打开原生浏览器时是两个浏览器啊,localStorage肯定不同,传参方式用路由传参!

小许继续努力!😃

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值