问题现象
在 iOS 夸克浏览器中点击"下载图片"按钮后:
- 页面显示 loading 进行图片生成
- 提示"图片已保存"
- 弹出"该网页请求打开外部应用,是否允许?"
- 点击"跳转"后打开错误的 APP
- 图片实际未保存到设备
根本原因
iOS 第三方浏览器(夸克、Chrome、QQ浏览器等)对 blob URL 下载 支持有限:
- blob URL 被误识别 :程序化创建
<a>标签触发 blob URL 下载时,浏览器可能将其识别为外部应用链接 - 安全策略拦截:非用户直接交互触发的下载可能被浏览器安全策略拦截
- 下载未真正执行:虽然代码执行完成并显示成功提示,但实际下载被浏览器阻止
解决方案
核心思路:区分 iOS Safari 和第三方浏览器,采用不同的下载策略。
ts
// 检测 iOS 第三方浏览器
const isIOSThirdPartyBrowser = (): boolean => {
const ua = navigator.userAgent;
const isIOS = /iPad|iPhone|iPod/.test(ua);
const isThirdParty = /CriOS|FxiOS|OPiOS|Quark|QQBrowser|UCBrowser|MicroMessenger|Weibo|DingTalk|Alipay/i.test(ua);
return isIOS && isThirdParty;
};
// 下载函数
export const downloadImageFileFromUrl = async (url: string, filename?: string) => {
// iOS 第三方浏览器:打开新窗口,让用户长按保存
if (isIOSThirdPartyBrowser()) {
window.open(url, '_blank', 'noopener,noreferrer');
return;
}
// iOS Safari 和其他平台:使用标准 blob 下载
const response = await fetch(url);
const blob = await response.blob();
const blobUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = blobUrl;
link.download = filename || 'image.png';
link.click();
setTimeout(() => URL.revokeObjectURL(blobUrl), 100);
};
用户提示适配
ts
// 根据浏览器类型显示不同提示
if (isIOSThirdPartyBrowser) {
message.success('请在新页面长按图片保存');
} else {
message.success('图片已保存');
}
影响范围
| 浏览器类型 | 下载方式 | 用户体验 |
|---|---|---|
| iOS Safari | blob 下载 | 直接下载到相册 |
| iOS 夸克/Chrome/QQ等 | window.open | 新页面长按保存 |
| Android/桌面浏览器 | blob 下载 | 直接下载 |
识别的第三方浏览器 UA 标识
CriOS- Chrome on iOSFxiOS- Firefox on iOSOPiOS- Opera on iOSQuark- 夸克浏览器QQBrowser- QQ 浏览器UCBrowser- UC 浏览器MicroMessenger- 微信Weibo- 微博DingTalk- 钉钉Alipay- 支付宝