是否在因为曾单线程下载速度缓慢而焦虑
http 可以范围请求
Range: <unit>=<range-start>-Range: <unit>=<range-start>-<range-end>Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
- unit:范围请求所采用的单位,通常是字节(bytes)。
:一个整数,表示在特定单位下,范围的起始值。 :一个整数,表示在特定单位下,范围的结束值。这个值是可选的,如果不存在,表示此范围一直延伸到文档结束。 方案
1. 通过
head请求获取到文件的长度xhr.getResponseHeader("Content-Length")
2. 通过
asyncPool来控制并发下载任务3. 实现一个根据参数发送范围请求的函数
下载 arrayBuffer 片段function getBinary (requestUrl, start, end, target) {return new Promise((rs, rj) => {try {let xhr = new XMLHttpRequest()xhr.open("GET", url, true)xhr.sendRequestHeader('range', `bytes=${start}-${end}`)xhr.responseType = 'arraybuffer'xhr.onload = function () {}xhr.send()} catch (err) {reject(new Error(err))}})}
[ArrayBuffer](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer)对象通过表示通用的,固定长度的原始二进制数据缓冲区,我们是不能对它直接操作的。而是要通过DataView或者 类型对象来操作,它会将缓冲区的数据表示为特定的格式,我们可以通过这些格式来读取缓冲区内容。4. 转化
ArrayBuffer为[Uint8Array](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)(八位无符号整型数组5. 通过 save 函数保存 FileSaver.js
```javascript function saveAs({ name, buffers, mime = “application/octet-stream” }) { const blob = new Blob([buffers], { type: mime }); const blobUrl = URL.createObjectURL(blob); const a = document.createElement(“a”); a.download = name || Math.random(); a.href = blobUrl; a.click(); URL.revokeObjectURL(blob); }
<a name="EjMgn"></a>##### 5. 最终实现```javascript// 获取到拼接后的 uint8Arrayasync function download({ url, chunkSize, poolLimit = 1 }) {}// 下载function multiThreadedDownload(url) {if (!url || !/https?/.test(url)) returnconsole.log("多线程下载开始: " + +new Date())download({url,chunkSize: 0.1 * 1024 * 1024,poolLimit: 6}).then((buffers) => {console.log('多线程下载结束: ' + +new Date())saveAs({ buffers, name: '我的压缩包', mime: 'application/zip' })})}
6. well done
你可能会质疑,下载速度取决于网络,并行明明会只是分摊带宽,为何会加速下载
其实用户端和服务器,都可以想象成两个水管
假设 服务器速度 a, 用户速度 b
单线程的时候
哪个速度小用哪个
多线程
a > b 用户带宽相当于受限,所以 这个时候多线程 只是起到分摊速度的效果
b > a 此时可以多线程加速下载
一般服务器会限制耽搁宽带的下载速度,往往是通过限制单个TCP下载,这种情况下,开启多线程是可以增加下载速度的,但有的也会限制单个IP的最大速度。
HTTP/1.1 同一站点只能并发六个请求,多余的会放到下一批次,但是 HTTP/2.0 不受这个限制,多路复用替代了 HTTP/1.1 的序列和阻塞机制
接着就可以愉快的下载了!
