一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何运用HTML的Fetch的Range请求头实现大文件分段断点续传机制

时间:2026-06-06 10:09:52 编辑:袖梨 来源:一聚教程网

Range请求头是HTTP协议中用于指定获取文件字节范围的字段,如“bytes=0-1023”,服务端支持时返回206状态码及对应数据,是实现断点续传的底层前提;其作用在于允许客户端跳过已下载部分,仅请求剩余字节,从而避免重复传输。

什么是 Range 请求头,它在断点续传里起什么作用

Range 是 HTTP 请求头,告诉服务器“我只要文件的某一段”,比如 Range: bytes=0-1023 表示要前 1KB。服务端如果支持,会返回 206 Partial Content 和对应字节范围的数据,而不是整个文件。这是断点续传的底层前提——没有 Range 支持,就无法跳过已下载部分。

但注意:不是所有服务器都默认响应 Range。静态资源(如 Nginx、Apache 默认配置下的 .zip/.mp4)通常支持;而 Node.js 的 express.static 默认也支持;但如果你用 fetch 请求的是后端 API 接口(比如 /api/download),那必须手动读取文件并设置 Content-Range 响应头,否则会返回 200 全量内容,Range 头被忽略。

用 fetch 发起带 Range 的请求,关键参数和常见错误

fetch 本身不禁止加 Range,但有几点容易踩坑:

  • Range 值必须是字符串,且格式严格:bytes=start-end(end 是包含的,不是长度)
  • 如果只想要从某处开始到结尾,写成 bytes=1024-,不能写 bytes=1024bytes=1024-*
  • 跨域请求时,Range 属于“CORS 预检敏感头”,需后端在 Access-Control-Allow-Headers 中显式声明允许,否则浏览器直接拒绝发送
  • 某些 CDN(如 Cloudflare 免费版)会剥离 Range 头或强制返回 200,导致断点失效,需确认 CDN 设置或绕过

示例请求:

立即学习“前端免费学习笔记(深入)”;

fetch(url, {  headers: {    'Range': 'bytes=5000000-9999999'  }})

如何组合多个 Range 请求实现分段下载与合并

浏览器中不能直接拼接 Blob 片段,必须用 Uint8Array 手动合并:

  • 每次 fetch 返回的 Response.arrayBuffer() 得到的是该段原始字节
  • 记录每段的起始偏移(start),用 new Uint8Array(totalSize) 初始化总缓冲区
  • 把每段 arrayBuffer 写入对应位置:total.set(new Uint8Array(segBuf), start)
  • 全部写完后,new Blob([total], {type: 'application/octet-stream'}) 生成完整文件

要点:

  • 必须提前知道文件总大小(可通过 HEAD 请求获取 Content-Length,或服务端在首次响应中返回)
  • 并发请求数不宜过多(建议 ≤ 4),否则可能触发服务端限流或连接复用问题
  • 某些服务器对 Range 的最小分块有限制(如要求 512 字节对齐),实际分段时最好按 1MB 对齐,避免边界错乱

断点状态如何持久化与恢复

断点信息不能只存在内存里,页面刷新就丢。推荐存到 localStorageIndexedDB

  • 存储结构至少含:urltotalSizecompletedRanges: [{start, end}]
  • 恢复时先查已下载区间,再计算剩余未覆盖的 [start, end] 列表
  • 注意:如果服务端文件被更新(ETagLast-Modified 变了),已有分段可能失效,应在恢复前用 HEAD 校验一致性

容易被忽略的一点:Chrome 对 localStorage 的写入是同步阻塞的,频繁更新进度(如每段完成就存)会导致 UI 卡顿。建议用防抖(debounce)或只在关键节点(如每 5 段、暂停时)保存。

热门栏目