You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android WebView应用如何在内部或跳转外部浏览器下载blob链接的PDF文件

问题根因

你当前代码无法下载blob格式URL的核心原因是系统DownloadManager不支持blob协议,blob是WebView当前会话内的临时内存地址,脱离WebView上下文直接请求会失效。

最简解决方案

步骤1:添加Blob下载JS交互接口

在你的MainActivity中添加如下内部类,用于接收WebView传回的文件内容:

public class DownloadBlobInterface {
    @JavascriptInterface
    public void downloadBlobFile(String base64Data, String fileName, String mimeType) {
        // 异步处理文件写入,避免阻塞JS线程
        new Thread(() -> {
            try {
                // 去除base64前缀
                String base64Content = base64Data.split(",")[1];
                byte[] fileBytes = android.util.Base64.decode(base64Content, android.util.Base64.DEFAULT);
                
                // 保存到公共下载目录
                File downloadDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
                File outputFile = new File(downloadDir, fileName);
                FileOutputStream fos = new FileOutputStream(outputFile);
                fos.write(fileBytes);
                fos.flush();
                fos.close();
                
                // 通知下载完成(切换到主线程弹吐司)
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "文件已保存到下载目录", Toast.LENGTH_SHORT).show());
                
            } catch (Exception e) {
                runOnUiThread(() -> Toast.makeText(MainActivity.this, "下载失败:" + e.getMessage(), Toast.LENGTH_SHORT).show());
            }
        }).start();
    }
}

步骤2:给WebView注册JS接口

在WebView初始化配置的位置添加一行代码:

// 原有WebView配置代码不变,新增下面这行
webView.addJavascriptInterface(new DownloadBlobInterface(), "AndroidDownloader");

步骤3:修改DownloadListener逻辑

替换你现有的onDownloadStart方法,区分普通URL和blob URL:

@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
    // 判断是否是blob协议的URL
    if (url.startsWith("blob:")) {
        String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
        // 拼接执行JS代码,把blob转成base64传回原生
        String jsCode = "javascript:(function() {" +
                "var xhr = new XMLHttpRequest();" +
                "xhr.open('GET', '" + url + "', true);" +
                "xhr.responseType = 'blob';" +
                "xhr.onload = function(e) {" +
                "    if (this.status == 200) {" +
                "        var blob = this.response;" +
                "        var reader = new FileReader();" +
                "        reader.readAsDataURL(blob);" +
                "        reader.onloadend = function() {" +
                "            var base64 = reader.result;" +
                "            AndroidDownloader.downloadBlobFile(base64, '" + fileName + "', '" + mimetype + "');" +
                "        }" +
                "    }" +
                "};" +
                "xhr.send();" +
                "})()";
        webView.loadUrl(jsCode);
        Toast.makeText(MainActivity.this, "正在下载文件...", Toast.LENGTH_SHORT).show();
    } else {
        // 非blob URL走你原来的DownloadManager逻辑
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        String cookies = CookieManager.getInstance().getCookie(userAgent);
        request.addRequestHeader("cookie",cookies);
        request.addRequestHeader("User-Agent",userAgent);
        request.setDescription("Downloading File....");
        request.setTitle(URLUtil.guessFileName(url,contentDisposition,mimetype));
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setDestinationInExternalPublicDir(
            Environment.DIRECTORY_DOWNLOADS,URLUtil.guessFileName(url,contentDisposition,mimetype));
        DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        downloadManager.enqueue(request);
        Toast.makeText(MainActivity.this, "Downloading File...", Toast.LENGTH_SHORT).show();
    }
}

补充权限配置

在AndroidManifest.xml中添加必要权限:

<!-- Android 13以下存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Android 12+下载通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.INTERNET" />

Android 6.0~12版本需要动态申请WRITE_EXTERNAL_STORAGE权限后再执行下载操作。

内容的提问来源于stack exchange,提问作者iChitti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 21:45:03