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

Cordova Android WebView无法下载服务器文件如何解决?

Cordova Android WebView 服务器文件下载实现方案

失效原因排查

你之前的方案无报错但不生效,核心是以下3个常见问题没有处理:

  • Android 10及以上版本的分区存储权限适配不到位
  • WebView默认未开启下载监听逻辑,不会拦截下载请求
  • 插件调用时的文件存储路径配置错误

前置配置要求

  • 在config.xml的Android平台配置块中添加权限和适配项:
    <!-- 基础存储权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    <!-- Android 13+ 媒体文件权限 -->
    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" android:minSdkVersion="33" />
    <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" android:minSdkVersion="33" />
    <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:minSdkVersion="33" />
    <!-- 适配Android 10分区存储 -->
    <application android:requestLegacyExternalStorage="true">
    <!-- 开启WebView文件访问权限 -->
    <preference name="AllowFileAccess" value="true" />
    <preference name="AllowUniversalAccessFromFileURLs" value="true" />
    
  • 确保Cordova Android平台版本≥10.1.0,低版本对新存储框架适配存在已知bug。

可行实现方案

方案1:原生WebView下载监听(无需额外下载插件)

直接在Android原生层给WebView添加系统下载管理器的监听,兼容性最好:

  1. 打开项目原生代码的MainActivity.java,在onCreate方法的loadUrl逻辑后添加如下代码:
    webView.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> {
        // 动态申请存储权限后再执行下载
        if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1001);
            return;
        }
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        dm.enqueue(request);
    });
    
  2. 权限申请回调中如果用户授权,重新触发下载即可。

方案2:cordova-plugin-file + cordova-plugin-file-transfer 正确调用

该方案适合需要在JS层全控制下载逻辑的场景,正确调用写法如下:

// 需先调用权限插件申请存储权限后再执行
const fileTransfer = new FileTransfer();
const downloadUrl = encodeURI("你的服务器文件完整下载地址");
// 必须用公共下载目录路径,私有目录下载后用户不可见
const savePath = cordova.file.externalRootDirectory + 'Download/' + '自定义文件名.后缀';

fileTransfer.download(
    downloadUrl,
    savePath,
    (entry) => {
        // 下载成功回调,可自行添加打开文件逻辑
        console.log("下载完成:" + entry.toURL());
    },
    (error) => {
        console.log("下载失败,错误码:" + error.code);
    },
    false,
    // 若下载需要鉴权,在此处添加请求头
    {
        headers: {
            "Authorization": "Bearer 你的鉴权令牌"
        }
    }
);

避坑提示

  • 不要直接使用HTML的download属性,Cordova Android WebView对跨域资源的download属性支持存在缺陷,基本不会触发下载。
  • 服务器返回下载响应时必须正确设置Content-Type和Content-Disposition响应头,否则文件会被WebView直接解析而不是触发下载。
  • 所有下载逻辑必须在用户授予存储权限后执行,不要在应用初始化阶段直接调用。
  • 调用cordova-plugin-file-transfer时必须使用cordova.file.externalRootDirectory等公共目录路径,私有目录路径下载的文件用户在系统文件管理器中无法查看。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:27:02