你可能已经知道上传大文件的解决方案了。在上传大文件时,为了提高上传效率,我们一般会使用Blob.slice方法将大文件切成若干块,并在所有块上传成功后通知服务器合并这些块。
那么对于大文件的下载,我们是否可以采用类似的思路呢?在服务器端支持Range请求头的条件下,我们也可以实现多线程的分块下载,如下图所示。
看完上图,相信你对大文件下载的解决方案有了一定的了解。接下来,我们就从HTTP范围请求说起。
什么是HTTP范围请求?
HTTP范围请求允许服务器只向客户端发送HTTP消息的一部分。范围请求在传输大型媒体文件时很有用,或者与恢复文件下载功能结合使用。如果响应中存在Accept-Ranges头(其值不是 "无"),那么服务器就支持范围请求。
在一个范围标头内,可以一次请求多个部分,服务器将把它们作为一个多部分文件返回。如果服务器返回一个范围响应,则需要206部分内容状态代码。如果请求的范围无效,服务器将返回416 Range Not Satisfiable状态代码,表示客户端错误。允许服务器忽略Range头并返回整个文件,状态码为200。
范围语法
Range: <unit>=<range-start>-
复制代码
- :指定范围的单位。这通常是字节。
- :一个在给定单位中的整数,表示请求范围的开始。
- :一个给定单位的整数,表示请求范围的结束。这个值是可选的,如果省略,文件的末尾将被视为范围的结束。
在了解了Range的语法后,让我们举几个例子。
单部分范围
$ curl
复制代码
多部分范围
$ curl
复制代码
这就是我们需要了解的关于HTTP范围请求的全部内容,所以让我们进入正题,开始介绍如何实现大文件下载。
如何实现大文件下载?
为了更好地理解下面的内容,让我们看一下整体的流程图。
在了解了大文件下载的过程后,我们先来定义上述过程中涉及的一些辅助函数。
1.定义getContentLength函数
这个函数是用来获取文件的长度的。我们通过发送HEAD请求,然后从响应头中读取Content-Length信息,得到当前URL对应的文件的内容长度。
2.定义asyncPool函数
asyncPool函数用于实现异步任务的并发控制。该函数接受3个参数。
- 并发性。并发限制数(>=1)
- iterable。一个输入的可迭代对象,如String、Array、TypedArray、Map和Set。
- iteratorFn。迭代器函数,需要两个参数:每次迭代的值和可迭代对象本身。迭代器函数应该返回一个承诺或者是一个异步函数。
3.定义getBinaryContent函数
getBinaryContent函数用于根据传递的参数发起一个范围请求,从而下载指定范围内的文件数据块。
注意ArrayBuffer对象是用来表示通用的、固定长度的原始二进制数据缓冲区的。我们不能直接操作ArrayBuffer的内容,而是通过TypedArray对象或DataView对象,以特定的格式表示缓冲区中的数据,并通过这些格式读写缓冲区的内容。
4.定义concatenate函数
由于ArrayBuffer对象不能直接操作,我们需要先将ArrayBuffer对象转换成Uint8Array对象,然后再进行合并操作。下面定义的concatenate函数就是用来合并下载的文件数据块的。具体代码如下。
5.定义saveAs函数
saveAs函数用于实现客户端的文件保存功能,这里只是一个简单的实现。在实际项目中,你可以考虑直接使用FileSaver.js。
在saveAs函数中,我们使用了Blob和Object URL。其中Object URL是一个伪协议,允许Blob和File对象作为图片、下载二进制数据的链接等的URL来源。
在浏览器中,我们使用URL.createObjectURL方法来创建一个Object URL,它接收一个Blob对象,并以blob:/的形式为其创建一个唯一的URL。
相应的例子如下。
blob:
复制代码
浏览器在内部为每个通过URL.createObjectURL生成的URL存储了一个URL→Blob映射。因此,这样的URL比较短,但可以访问blob。生成的URL只有在当前文档打开的情况下才有效。
6.定义下载函数
下载函数用于执行下载操作,它支持3个参数。
- url。资源的URL
- chunkSize。块的大小,以字节为单位
- poolLimit:限制并发的数量。
7.大文件并发下载完整示例
使用上面定义的辅助函数,我们可以轻松实现大文件的并发下载。
完整的代码如下。
本文介绍了如何使用JavaScript中的asyncPool函数来实现大文件的并发下载。它还描述了如何通过HEAD请求获得文件大小,如何发起HTTP范围请求,以及如何在客户端保存文件。
资源
位:建立更好的UI组件库
向你问好 比特.它是组件驱动的应用开发的第一大工具。
有了Bit,你可以将你的应用程序的任何部分创建为一个可组合和可重用的 "组件"。你和你的团队可以共享一个组件工具箱,以便更快、更一致地共同构建更多的应用程序。
- 创建和组成 "应用构件"。UI元素、完整功能、页面、应用程序、无服务器或微服务。使用任何JS堆栈。
- 在团队中轻松分享和重复使用组件。
- 跨项目快速更新 组件。
- 让困难的事情变得简单。单体、设计系统和微前端。
了解更多
在JavaScript中实现大文件的并发下载》最初发表在《Bits and Pieceson Medium》上,人们通过强调和回应这个故事来继续对话。