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

RNFetchBlob多文件并行下载如何实现断网暂停自动续传

断网自动暂停+断点续传多文件下载实现方案

核心实现逻辑

整体拆为4个模块:网络状态实时监听、单任务断点续传能力、队列任务保活机制、断网任务终止/恢复调度。

完整实现代码

1. 基础依赖与全局状态定义

需要先安装网络监听库:yarn add @react-native-community/netinfo

import RNFetchBlob from 'rn-fetch-blob'
import NetInfo from "@react-native-community/netinfo";

// 全局状态
let isNetworkAvailable = true;
let files_que = [...items];
// 存储每个文件的断点位置:key为文件唯一标识,value为已下载字节数
const breakPointMap = new Map();
// 存储正在执行的下载任务句柄,断网时可批量取消
const activeDownloadTasks = new Map();
// 并发下载数
const CONCURRENT_LIMIT = 2;

2. 支持断点续传的单文件下载方法

/**
 * 断点续传下载单文件
 * @param {string} url 下载地址
 * @param {string} savePath 本地存储路径
 * @param {string} fileKey 文件唯一标识
 */
const processdownloadVideo = (url, savePath, fileKey) => {
  return new Promise(async (resolve, reject) => {
    // 读取本地已下载文件大小,作为续传起始点
    let downloadedSize = 0;
    try {
      const fileStat = await RNFetchBlob.fs.stat(savePath);
      downloadedSize = fileStat.size;
      breakPointMap.set(fileKey, downloadedSize);
    } catch (err) {
      // 文件不存在则从0开始下载
      downloadedSize = 0;
    }

    // 当前无网络直接挂起
    if (!isNetworkAvailable) {
      return reject({ type: 'network_suspend', fileKey });
    }

    // 发起带Range头的续传请求
    const downloadTask = RNFetchBlob.config({
      path: savePath,
      appendExt: false, // 开启追加写入模式
    })
    .fetch('GET', url, {
      Range: `bytes=${downloadedSize}-`,
    })
    .progress({ interval: 250 }, (received) => {
      // 实时更新断点位置
      breakPointMap.set(fileKey, downloadedSize + received);
    });

    activeDownloadTasks.set(fileKey, downloadTask);

    downloadTask.then(async (res) => {
      breakPointMap.delete(fileKey);
      activeDownloadTasks.delete(fileKey);
      // 200为全量下载成功、206为断点续传成功
      const status = res.info().status;
      if (status === 200 || status === 206) {
        resolve(res);
      } else {
        reject({ type: 'download_error', err: new Error(`HTTP状态异常:${status}`), fileKey });
      }
    }).catch((err) => {
      activeDownloadTasks.delete(fileKey);
      reject(
        isNetworkAvailable 
          ? { type: 'download_error', err, fileKey }
          : { type: 'network_suspend', fileKey }
      );
    });
  });
};

3. 支持断网等待的下载队列worker

const downloadWorker = async () => {
  while (files_que.length > 0) {
    // 无网络时循环等待,不消费队列
    if (!isNetworkAvailable) {
      await new Promise(resolve => {
        const waitTimer = setInterval(() => {
          if (isNetworkAvailable) {
            clearInterval(waitTimer);
            resolve();
          }
        }, 1000);
      });
    }

    const currentFile = files_que.shift();
    const fileKey = currentFile.uri;
    const savePath = `path/${currentFile.uri}`;

    try {
      await processdownloadVideo(currentFile.http_uri, savePath, fileKey);
    } catch (err) {
      if (err.type === 'network_suspend') {
        // 断网导致的中断,把任务放回队列头部,恢复后优先下载
        files_que.unshift(currentFile);
        await new Promise(resolve => setTimeout(resolve, 1000));
      } else {
        // 非网络错误可自定义重试逻辑,比如最多重试3次再标记失败
        console.log('文件下载失败', err);
      }
    }
  }
};

4. 网络监听与下载启动逻辑

// 初始化网络状态监听
const initNetworkMonitor = () => {
  return NetInfo.addEventListener(state => {
    const currentNetStatus = state.isConnected && state.isInternetReachable;
    // 联网切断网:取消所有正在进行的下载任务,避免资源占用
    if (isNetworkAvailable && !currentNetStatus) {
      isNetworkAvailable = false;
      activeDownloadTasks.forEach(task => task.cancel());
      activeDownloadTasks.clear();
    }
    // 断网切联网:更新状态,worker会自动恢复消费队列
    if (!isNetworkAvailable && currentNetStatus) {
      isNetworkAvailable = true;
    }
  });
};

// 启动多文件下载
const startBatchDownload = () => {
  const removeNetListener = initNetworkMonitor();
  const workers = Array(CONCURRENT_LIMIT).fill(null).map(() => downloadWorker());
  return Promise.all(workers).finally(() => removeNetListener());
};

注意事项

  • 服务端必须支持Range请求头,否则断点续传无法生效,大部分静态资源服务默认开启该能力,自研服务需要单独配置
  • 如果需要APP重启后续传,可以将files_que和breakPointMap持久化到本地存储(比如AsyncStorage),APP启动时读取数据恢复队列即可
  • 建议给非网络类错误增加重试次数限制,避免异常任务一直阻塞队列
  • 并发数建议设置为2-3,过高容易触发服务端限流,也会占用过多设备带宽

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 23:24:31