场景

最新在做一个H5功能,做附件下载。

适用场景: 新窗口打开一个连接。

思路

根据附件id查询出附件地址之后,利用 window.open(failUrl) 打开新窗口来下载附件。

现象

安卓手机所测试的常用浏览器基本上都没问题,唯独iphone手机自带的safari浏览器不生效。

解决办法

对safari浏览器做特殊判断。

判断safari浏览器的方法

/* 判断是否是ios手机safari浏览器打开的 */
export const isIosSafari = () => {
const ua = navigator.userAgent.toLowerCase();
if (
ua.indexOf('applewebkit') > -1 &&
ua.indexOf('mobile') > -1 &&
ua.indexOf('safari') > -1 &&
!(ua.indexOf('android') > -1) &&
!(ua.indexOf('linux') > -1) &&
!(ua.indexOf('crios') > -1) &&
!(ua.indexOf('chrome') > -1) &&
!(ua.indexOf('browser') > -1) &&
!(ua.indexOf('ios') > -1)
) {
return true;
}
return false;
};

方案一 (推荐)

先打开一个空白窗口,然后再给窗口赋值地址。

// 按钮
 this.handleDownload(item)}>下载文件
/* 下载文件方法 */
handleDownload = (item) => {
const { dispatch } = this.props;
// 要先定义打开新窗口,否则也会被拦截 不生效
const winRef = window.open("about:blank","_blank");
dispatch({
type: 'common/downloadFile',
payload: { fileId: item.fileId },
callback: (data) => {
// 后台接口返回回来的地址 fileUrl1
const fileUrl1 = data.fileUrl;
winRef.location = fileUrl1;
}
});
};

如果const winRef = window.open("about:blank","_blank");放在异步回调函数中,恭喜你,不会生效,会被拦截哟~

方案二

当时safari浏览器的时候,我们通过超链接点击来跳转。

创建的标签,执行TagA.click()方法,在safari上也是不生效的,有老铁说safari下的A标签默认是没有绑定事件,那么我们就可以手动绑定一个事件,然后触发即可。

/* 利用a标签下载附件 */
downloadFileByTagA = (fileUrl) => {
const TagA = document.createElement('a');
TagA.href = fileUrl;
// TagA.target = '__blank';
document.body.appendChild(aSpan);
TagA.className = 'oInput';
TagA.style.display = 'none';
// 兼容ios safari浏览器
const e = document.createEvent('MouseEvent');
e.initEvent('click', false, false);
TagA.dispatchEvent(e);
}

上诉👆代码我注释掉了TagA.target = '__blank'; 应为我加上去之后就不生效了,被safari安全机制拦截了。

当然这个可以通过 苹果系统设置,偏好设置->安全性,去掉阻止弹窗的复选框 来解决~~~。

方案三

生成一个a标签,让用户自己去点击。这个无论如何都不会被拦截。

不过这样也不好,会使用户多一步操作。

方案四

苹果系统设置,偏好设置->安全性,去掉阻止弹窗的复选框,如上所述。不太推荐,改变了用户的主观意愿

复盘分析

首先连接是无论如何不会被拦截的,可以生成一个连接让用户去点击,这样不太友好~~~


我是一个连接呀

为什么会被拦击呢?

当然是window.open被广告商滥用,严重影响用户的使用。

当然也不是所有的window.open都会被拦截,我们只需要找准时机去触发即可。

避免在回调函数中去执行window.open方法。