admin管理员组

文章数量:1644414

背景

没错,你没有看错,是前端多线程,而不是Node。这一次的探索起源于最近开发中,有遇到视频流相关的开发需求发现了一个特殊的状态码,他的名字叫做 206~

屏幕快照 2020-09-21 23.21.05

为了防止本文的枯燥,先上效果图镇文。(以一张3.7M 大小的图片为例)。

动画效果对比(单线程-左 VS 10个线程-右)

single-vs-multiple-donwload

时间对比(单线程 VS 10个线程)

image-20200915235421355

看到这里是不是有点心动,那么请你继续听我道来,那我们先抓个包来看看整个过程是怎么发生的。

GET /360_0388.jpg HTTP/1.1
Host: limit.qiufeng
Connection: keep-alive
...
Range: bytes=0-102399

HTTP/1.1 206 Partial Content
Server: openresty/1.13.6.2
Date: Sat, 19 Sep 2020 06:31:11 GMT
Content-Type: image/jpeg
Content-Length: 102400
....
Content-Range: bytes 0-102399/3670627

...(这里是文件流)

可以看到请求这里多出一个字段 Range: bytes=0-102399 ,服务端也多出一个字段Content-Range: bytes 0-102399/3670627,以及返回的 状态码为 206.

那么Range是什么呢?还记得前几天写过一篇文章,是关于文件下载的,其中有提到大文件的下载方式,有个叫 Range的东西,但是上一篇作为系统性地介绍文件下载的概览,因此没有对range 进行详细介绍。

以下所有代码均在 https://github/hua1995116/node-demo/tree/master/file-download/example/download-multiple

Range 基本介绍

Range的起源

Range是在 HTTP/1.1 中新增的一个字段,这个特性也是我们使用的迅雷等支持多线程下载以及断点下载的核心机制。(介绍性的文案,摘录了一下)

首先客户端会发起一个带有Range: bytes=0-xxx的请求,如果服务端支持 Range,则会在响应头中添加Accept-Ranges: bytes来表示支持 Range 的请求,之后客户端才可能发起带 Range 的请求。

服务端通过请求头中的Range: bytes=0-xxx来判断是否是进行 Range 处理,如果这个值存在而且有效,则只发回请求的那部分文件内容,响应的状态码变成206,表示Partial Content,并设置Content-Range。如果无效,则返回416状态码,表明Request Range Not Satisfiable。如果请求头中不带 Range,那么服务端则正常响应,也不会设置 Content-Range 等。

Value Description
206 Partial Content
416 Range Not Satisfiable

Range的格式为:

Range:(unit=first byte pos)-[last byte pos]

Range: 单位(如bytes)= 开始字节位置-结束字节位置

我们来举个例子,假设我们开启了多线程下载,需要把一个5000byte的文件分为4个线程进行下载。

  • Range: bytes=0-1199 头1200个字节
  • Range: bytes=1200-2399 第二个1200字节
  • Range: bytes=2400-3599 第三个1200字节
  • Range: bytes=3600-5000 最后的1400字节

服务器给出响应:

第1个响应

  • Content-Length:1200
  • Content-Range:bytes 0-1199/5000

第2个响应

  • Content-Length:1200
  • Content-Range:bytes 1200-2399/5000

第3个响应

  • Content-Length:1200
  • Content-Range:bytes 2400-3599/5000

第4个响应

  • Content-Length:1400
  • Content-Range:bytes 3600-5000/5000

如果每个请求都成功了,服务端返回的response头中有一个 Content-Range 的字段域,Content-Range 用于响应头,告诉了客户端发送了多少数据,它描述了响应覆盖的范围和整个实体长度。一般格式:

Content-Range: bytes (unit first byte pos) - [last byte pos]/[entity length]Content-Range࿱

本文标签: 大文件多线程axios