利用js纯前端实现多线程下载及断点续传

多线程下载、断点续传在各类网盘中已经屡见不鲜了,但是那些基本都是桌面端软件,就拿百度网盘来说,其网页端也并没有支持多线程下载,而是采用了浏览器默认的下载方式,这种浏览器默认提供的下载方式确实很好用,但是十项如果我们要下载的文件非常大,达到了以G计数的大小,那么这种下载方式的弊端就展现出来了,

1、下载速度慢,可能要1个小时左右才能下载完。

2、虽然说浏览器实现了断点续传,但是如果下载到一半出现异常,还是有几率会让我们从头重下,这种体验未免有些糟糕。

那么我们如果用前端技术来助力多线程下载和断点续传呢?可能很多人会觉得这个一定需要后端配合我们才可能做到,但是我今天想告诉你,我们要用纯前端技术加一点服务器的知识实现多线程下载和断点续传,完全不用后端的配合,在开始之前我们需要先了解一下HTTP的范围请求。

一、是否支持范围请求

HTTP 本身是一种无状态的“松散”协议,在经历了很多版本的迭代之后, 在HTTP/1,1(RFC2616)之后支持了范围请求,并明确声明了响应头 accept-ranges 用于标记是否支持范围请求,而他只有一个可选参数bytes,

如果下载文件时响应头返回了accept-ranges:bytes, 说明该文件支持范围请求,我们可以对其做多线程下载,这里注意不要再服务端强制加响应头accept-ranges:bytes,虽然头能加上去,但是会出现一个很诡异的问题,这个我们后面再说。

二、如何使用范围请求实现下载?

根据上面的知识我们已经知道了如何判别一个文件是否支持范围请求,那么我们如何在请求资源的时候使用它呢?

我们知道文件其实最终都是存储在磁盘或内存中的字节组成的,而对于每一个文件我们都可以将其分割为以字节为单位的小块,我们可以将文件根据一定的步长或者范围划分成n多小片,然后分别请求这些小片段得到片段内的字节,在所有小片都下载完成后,合并这些字节不就可以得到一个完整的文件了吗?

为了迎合 响应头accept-ranges: bytes,HTTP/1.1同时定义了ranges请求头用于直接请求文件的范围,其范围取值在0-content-length(也是一个响应头)之间,使用字符-分割。

range根据需要可以灵活选用以下几种不同的方式来限定范围。

1、0-100:指定开始和结束的范围,指取0-100范围内的数据

2、-100:无开始区间,指取最后100bytes的数据

3、100-:指定开始区间,无结束区间,指从100bytes一直取到文件结束

4、0-100,101-200:指定多个范围区间,这种了解一下就好了

使用时我们只需要增加请求头ranges:bytes=0-100就行了。

当我们使用range请求头来请求文件时,服务端也会响应content-range来标记响应实体的内容范围。

格式如上图所示,Content-Range: bytes 0-100/8003979,0-100表示请求的范围,8003978表示文件的总大小,而这里需要大家注意状态码是206 Partial Content,不是200,回到上面我们提到的强制加响应头 accept-ranges: bytes 会导致一个诡异的问题,就是这边的状态码会是200而不是206,整个流程看不出问题,但最终合成的文件大小会是原始文件大小的n倍,n等于分片数的大小。关于206状态码的结束大家可以参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status/206

三、范围请求助力多线程下载及断点续传

知道了范围请求实现多线程下载就很简单了,无非根据文件大小和指定的分片大小,将文件分片,实现一个多线程下载队列,多线程并行下载文件分片,在所有分片下载完成后合并文件就好了。至于断点续传不过就是一些优化体验的手段,记录下下载失败的分片,重新下载跳过已经正确下载的分片,只下载失败的分片,最终在所有分片下载完成后合成文件。

四、实现过程中可能遇到的一些问题

1、很多朋友可能会想,我把一个几G的文件下载到内存中会不会导致浏览器爆掉,经过调研完全就是多虑了,范围请求下来的文件浏览器做了优化并没有放在内存中,而是以临时文件的形式存在了磁盘上,而且就算网站常用的资源文件,也不是所有都会放在内存中的,浏览器会根据文件可能使用的频率将文件放在内存中或者存在磁盘中。

2、很多人可能会问分片下载完成后怎么合并文件?怎么下载文件?其实我们下载完成后就可以得到文件分片的blob,将这些文件分片的blob就可以合并为大文件的blob,通过blob生成url,然后触发浏览器默认的下载就可以了,这里的浏览器的默认下载很非常快,大家不必担心。

结语

封装了一个通用类用于实现了多线程下载队列、和断点重下机制,下载进度和简单的时间预测,可以直接在项目中使用有需要的朋友可以在下方链接中获取源码。

猛戳这里下载本文案例源码包
  • 支付宝二维码 支付宝
  • 微信二维码 微信
相关文章