webview 中文文档 下载 App

WebView 里 blob: URL 被拦截——扫码下载、PDF 预览为什么突然不行

问题场景

App 内嵌网页里点击"下载附件" → 网页代码用 URL.createObjectURL(blob) 生成一个 blob:https://xxx/xxx 格式的下载链接 → 点击后什么都不发生。

典型案例:

为什么发生

WebView 里 blob: 格式的下载链接触发时,需要走 WebChromeClient 的 onShowFileChooser 回调。但部分厂商在 WebView 层面默认禁用了 blob: 协议——下载事件根本到不了 onShowFileChooser。

厂商默认 blob 策略可解吗
小米 HyperOS默认拦截应用层手动放开
华为 ArkWeb默认拦截鸿蒙 API 层配置
Google Android System WebView默认允许——
OPPO / vivo / Samsung默认允许——

小米 HyperOS 的解法

需要在 WebView 初始化时手动开启 blob 协议:

WebSettings settings = webView.getSettings();
settings.setAllowContentAccess(true);  // 必须开

// 小米 HyperOS 特有:放开 blob: 协议
try {
    Class<?> clazz = Class.forName("com.android.webview.Settings");
    Method m = clazz.getMethod("setAllowBlobUrls", boolean.class);
    m.invoke(settings, true);
} catch (Exception e) {
    // 非 HyperOS 设备走默认行为
}

这个 API 是小米私有的(非 Android 标准 API),需要反射调用,而且版本变化可能失效。

华为 ArkWeb 的解法

鸿蒙上需要用 ArkWeb 专有 API:

// JS 端显式配置下载
const link = document.createElement('a');
link.href = blobUrl;
link.download = filename;
link.click();

// 如果还是不行,尝试手动触发下载事件
link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }));

鸿蒙 WebView 默认拦截非 HTTPS 来源的 blob 下载,尝试让后端改成 HTTPS 响应再试。

更通用的解法

与其依赖 blob 下载,不如服务端直接提供可下载的 URL(HTTPS),让 WebView 用标准下载流程:

// App 端拦截下载,调用系统下载管理器
webView.setDownloadListener(new DownloadListener() {
    @Override
    public void onDownloadStart(String url, String u, String m, String c, long l) {
        // 交给 DownloadManager 或自己处理
    }
});

这样绕过了 blob 协议安全限制,所有厂商的 WebView 都适用。

→ 继续:HarmonyOS NEXT 开发者完整清单