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

如何使用Cordova下载160GB大文件?XMLHttpRequest加载大文件无响应问题求助

如何使用Cordova下载160GB大文件?XMLHttpRequest加载大文件无响应问题求助

兄弟,你遇到的问题其实很典型——用XHR把160GB的文件直接加载成Blob,这完全超出了Cordova WebView的内存承受能力,直接导致进程崩溃或者无响应,连错误事件都来不及触发,所以只打印了个5就挂了。

问题根源

当你设置req.responseType = "blob"时,XHR会把整个文件先加载到内存里再触发后续事件。160GB的文件远超过移动设备WebView的内存上限(一般也就几百MB到几GB),系统直接就把进程掐了,自然不会触发任何回调,也没机会进入catch块。

解决方案:分块下载+边下边存

核心思路是不要一次性加载整个文件,而是把文件分成小块(比如10MB一块),每次只下载一段,下载完成后立刻写入本地文件,循环直到整个文件下载完毕。配合Cordova的cordova-plugin-file插件就能实现,这样不会占用大量内存。

具体实现步骤&代码示例

  1. 先获取本地存储目录,创建一个空文件用于写入
  2. 用Range请求头分段请求文件内容
  3. 每下载一块就追加写入本地文件,更新偏移量后继续下载下一块
// 配置参数
const FILE_URL = "你的大文件地址";
const TOTAL_FILE_SIZE = 160 * 1024 * 1024 * 1024; // 160GB
const CHUNK_SIZE = 10 * 1024 * 1024; // 每次下载10MB
let currentOffset = 0;
let targetFileEntry;

// 第一步:初始化本地文件
function initLocalFile() {
  // 获取Cordova的外部数据目录(可根据需求换其他目录)
  window.resolveLocalFileSystemURL(
    cordova.file.externalDataDirectory,
    (dirEntry) => {
      dirEntry.getFile(
        "large_download_file.bin",
        { create: true, exclusive: false },
        (fileEntry) => {
          targetFileEntry = fileEntry;
          console.log("本地文件创建完成,开始分块下载");
          downloadNextChunk();
        },
        (err) => console.error("创建本地文件失败:", err)
      );
    },
    (err) => console.error("获取存储目录失败:", err)
  );
}

// 第二步:下载下一块文件
function downloadNextChunk() {
  if (currentOffset >= TOTAL_FILE_SIZE) {
    console.log("✅ 整个文件下载完成!");
    return;
  }

  // 计算当前块的起止字节
  const endOffset = Math.min(currentOffset + CHUNK_SIZE - 1, TOTAL_FILE_SIZE - 1);
  const xhr = new XMLHttpRequest();

  xhr.open("GET", FILE_URL, true);
  // 设置Range请求头,告诉服务器只返回指定区间的内容
  xhr.setRequestHeader("Range", `bytes=${currentOffset}-${endOffset}`);
  xhr.responseType = "blob";

  xhr.onload = () => {
    // 206是部分内容的状态码,200可能是最后一块或服务器不支持Range
    if (xhr.status === 206 || xhr.status === 200) {
      writeChunkToFile(xhr.response);
    } else {
      console.error(`分块下载失败,状态码: ${xhr.status}`);
    }
  };

  xhr.onerror = (err) => console.error("分块请求出错:", err);
  xhr.send();
}

// 第三步:将下载的块写入本地文件
function writeChunkToFile(blob) {
  targetFileEntry.createWriter(
    (writer) => {
      // 定位到当前偏移量,实现追加写入
      writer.seek(currentOffset);
      writer.write(blob);

      writer.onwriteend = () => {
        currentOffset += blob.size;
        const progress = ((currentOffset / TOTAL_FILE_SIZE) * 100).toFixed(2);
        console.log(`📥 已下载${progress}%`);
        // 继续下载下一块
        downloadNextChunk();
      };

      writer.onerror = (err) => console.error("写入文件失败:", err);
    },
    (err) => console.error("获取文件写入器失败:", err)
  );
}

// 启动下载
initLocalFile();

额外注意事项

  • 服务器支持Range请求:先发送一个HEAD请求,检查服务器返回的Accept-Ranges头是否为bytes,如果不支持Range,分块下载就无法进行。
  • 权限配置:Cordova需要配置文件读写权限,Android在config.xml中添加:
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- Android 10+ 可能需要额外配置Scoped Storage或MANAGE_EXTERNAL_STORAGE权限 -->
    
    iOS需要在info.plist中添加文件访问权限描述,比如NSPhotoLibraryAddUsageDescription。
  • 后台下载:如果需要APP退到后台仍能下载,建议使用专门的Cordova插件(比如cordova-plugin-background-downloader),这类插件调用原生系统的下载管理器,稳定性更高。

备注:内容来源于stack exchange,提问作者user3523426

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 15:47:29