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

使用AJAX下载大型二进制文件断网时如何获取已接收的HTTP请求数据?

下载中断时保存已接收二进制数据的实现方法

核心原理

普通AJAX默认会等待全部响应数据接收完成后才对外暴露完整响应内容,要拿到中断前的部分数据,需要使用流式读取能力,在数据逐块到达时就进行暂存,触发断开事件时直接导出已暂存的数据。

可选实现方案

方案1:Fetch API + ReadableStream(主流浏览器适配,推荐)

Fetch API原生支持流式读取响应体,你可以逐块接收二进制数据,任意节点触发异常时都可以直接导出已接收的块:

  • 调用fetch()发起请求,从返回的Response对象中获取body对应的ReadableStream读取器
  • 循环读取响应的chunk块,存入数组累积
  • 监听请求错误或中断事件,触发时将已累积的chunk拼接为Blob导出到本地

示例代码:

async function streamDownload(url, fileName) {
  const chunks = [];
  let isCompleted = false;

  try {
    const res = await fetch(url);
    if (!res.ok) throw new Error(`请求失败,状态码:${res.status}`);
    const reader = res.body.getReader();

    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        isCompleted = true;
        break;
      }
      chunks.push(value);
      // 可选:大文件场景下可定时将chunk写入IndexedDB,避免内存溢出
    }
  } catch (err) {
    console.warn('下载中断,将导出已接收数据');
  } finally {
    if (chunks.length && !isCompleted) {
      // 导出已下载内容
      const blob = new Blob(chunks);
      const downloadLink = document.createElement('a');
      downloadLink.href = URL.createObjectURL(blob);
      downloadLink.download = fileName;
      downloadLink.click();
      URL.revokeObjectURL(downloadLink.href);
    }
  }
}

方案2:XMLHttpRequest 兼容方案(适配老旧浏览器)

如果需要兼容不支持Fetch API的旧版浏览器,可以使用XHR的进度事件暂存已接收数据:

  • 设置XHR的responseType为arraybuffer,避免二进制数据被编码损坏
  • 监听progress事件,每次事件触发时将当前已接收的完整response暂存
  • 触发error中断事件时,直接将暂存的buffer转为Blob导出

示例代码:

function xhrDownload(url, fileName) {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.responseType = 'arraybuffer';
  let receivedBuffer = null;

  xhr.addEventListener('progress', () => {
    if (xhr.response) receivedBuffer = xhr.response;
  });

  // 下载中断触发
  xhr.addEventListener('error', () => {
    if (!receivedBuffer) return;
    const blob = new Blob([receivedBuffer]);
    const downloadLink = document.createElement('a');
    downloadLink.href = URL.createObjectURL(blob);
    downloadLink.download = fileName;
    downloadLink.click();
    URL.revokeObjectURL(downloadLink.href);
  });

  // 下载完成逻辑
  xhr.addEventListener('load', () => {
    const blob = new Blob([xhr.response]);
    const downloadLink = document.createElement('a');
    downloadLink.href = URL.createObjectURL(blob);
    downloadLink.download = fileName;
    downloadLink.click();
    URL.revokeObjectURL(downloadLink.href);
  });

  xhr.send();
}

注意事项

  • 跨域场景下需要服务端配置对应的CORS规则,否则请求会被浏览器拦截
  • 超过1GB的超大文件建议将接收的分片定时写入IndexedDB存储,避免内存占用过高导致页面崩溃
  • 如果需要实现断点续传,可要求服务端支持Range请求头,下次下载时携带Range: bytes=已下载字节数-即可从上次中断位置继续下载,拼接历史数据即可得到完整文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 15:24:05