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

Chrome批量下载图片触发ERR_INSUFFICIENT_RESOURCES错误解决方案咨询

问题根因

Chrome 对同一上下文下未完成的异步请求数量有严格的资源限制,你一次性发起5000个并发请求,大量请求进入pending队列后超出浏览器内存/请求数阈值,就会抛出ERR_INSUFFICIENT_RESOURCES错误,Firefox的阈值设置更高因此可以正常执行。

可行解决方案

核心思路是限制并发请求数,浏览器同域名的默认并发请求上限为6~8,你把同一时间活跃的请求数控制在这个范围内即可,多余请求排队等待空闲 slot 再发起,既不会触发资源报错,也不会降低实际下载效率。

具体实现步骤:

  • 第一步:编写轻量并发控制器,无需引入第三方依赖,逻辑如下:
// 并发请求控制器,limit为同一时间最多活跃的请求数
function concurrencyController(tasks, limit = 6) {
  let activeCount = 0
  let index = 0
  const results = []
  return new Promise((resolve) => {
    function run() {
      // 所有请求执行完成后返回结果
      if (index >= tasks.length && activeCount === 0) {
        resolve(results)
        return
      }
      // 有空闲slot时发起新请求
      while (activeCount < limit && index < tasks.length) {
        const task = tasks[index]
        const currentIndex = index
        index++
        activeCount++
        task().then(res => {
          results[currentIndex] = res
        }).catch(err => {
          // 可自定义错误处理,比如记录失败的fileId后续重试
          results[currentIndex] = null
        }).finally(() => {
          activeCount--
          run()
        })
      }
    }
    run()
  })
}
  • 第二步:改造原有下载函数,改为返回Promise的形式,移除全局变量依赖:
function loadFileAndDecrypt(fileId, key, type) {
  return new Promise((resolve, reject) => {
    const req = new dh.crypto.HttpRequest();
    req.setAesKey(key);
    const dataUrl = type == "study" ? "/v1/images/" : "/v1/dicoms/";
    const url = axios.defaults.baseURL + dataUrl + fileId;
    req.open("GET", url, true);
    req.setRequestHeader("Authorization", authHeader().Authorization+"")
    req.setRequestHeader("Accept", "application/octet-stream, application/json, text/plain, */*");
    req.responseType = "arraybuffer";

    req.onload = function() {
        resolve(req.response);
    };
    req.onerror = reject
    req.send();
  })
}
  • 第三步:批量发起请求时通过控制器限制并发,同时处理进度回调:
async function batchDownload(fileIdList, key, type, callback) {
  const total = fileIdList.length
  let downloadStep = 0
  const step = 100 / total
  eventBus.$emit('updateProgressText', "downloadingFiles")
  // 包装所有下载任务
  const tasks = fileIdList.map(fileId => () => {
    return loadFileAndDecrypt(fileId, key, type).then(res => {
      // 单请求完成后更新进度
      downloadStep += step
      eventBus.$emit('updatePb', Math.ceil(downloadStep))
      return res
    })
  })
  // 控制并发数执行
  const downloadResults = await concurrencyController(tasks, 6)
  // 过滤失败请求,也可自定义重试逻辑
  const validResults = downloadResults.filter(Boolean)
  callback(validResults)
}

可选优化点

  • 增加单请求失败重试逻辑,偶发网络错误时自动重试2~3次,避免批量下载中途失败
  • 如果资源允许跨域,可替换自定义HttpRequest为原生fetch API,内存占用更低
  • 若业务允许边下载边处理,不要一次性将5000份ArrayBuffer全部存在内存中,避免后续页面卡顿

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 05:15:04