在服务器支持范围请求头的情况下,我们也可以实现多线程块下载功能,如下图所示:
看了上图,相信你对下载大文件的方案有了一定的了解。接下来,我们先介绍一下HTTP作用域请求。
首先,HTTP作用域请求HTTP协议作用域请求允许服务器只向客户端发送HTTP消息的一部分。传输大型媒体文件时,或与文件下载的断点续传功能配合使用时,范围请求非常有用。
如果响应中有一个Accept-Ranges头(并且它的值不是“none”),这意味着服务器支持范围请求。在范围标题中,可以一次请求多个零件。
服务器将把它作为一个多部分文件返回。如果服务器返回范围响应,您需要使用206部分内容状态代码。如果请求的范围不合法,
则服务器将返回416范围不可满足状态代码,指示客户端错误。服务器允许忽略范围头,从而返回整个文件,状态码为200。
1.1 Range语法range:=-range:=-range:=-,-range:=-,-unit:范围请求中使用的单位,通常为字节。整数,
以特定单位表示范围的起始值。以特定单位表示范围结束值的整数。该值是可选的。如果不存在,则意味着该范围延伸到文档的末尾。理解了范围语法之后,我们来看看实际使用的例子:
1.1.1 single range $ curl http://i.imgur.com/z4d4kWk.jpg-I-H' range: byte=0-1023'1.1.2 multiple range $ curl http://www.example.com-I-H' range: byte=0-50,100-150'
二、如何下载大文件为了让大家更好的理解下面的内容,我们来看一下整体流程图:
了解了下载大文件的流程后,我们先来定义一下上述流程中涉及到的一些辅助功能。
2.1定义辅助函数2.1.1定义getContentLength函数顾名思义,用来获取文件的长度。在这个函数中,我们发送一个HEAD请求,
然后从响应头中读取Content-Length信息,然后获取当前url对应的文件的内容长度。
函数get contentlength(URL){ return new Promise((resolve,reject)={ let xhr=new XMLHttpRequest();xhr.open('HEAD 'URL);xhr。send();xhr。onload=function(){ resolve(~ ~ xhr。getresponse头(' Content-Length ');};xhr . on error=reject });}2.1.2 定义异步池函数在Java脚本语言中如何实现并发控制?这篇文章中,
Asynchronous function asyncPool(poolLimit, array, iteratorfn) {constret=[]; //Store all asynchronous tasks const executing=[]; //Store the executing asynchronous task for (the constant item of the array) {//Call the iterator Fn function to create the asynchronous task const p=Promise.resolve (). Then (()=iteratorFn(item, array));); ret . push(p); //Save a new asynchronous task//When the pool limit value is less than or equal to the total number of tasks,
函数getBinaryContent(url,start,end,i) { return new Promise((resolve,reject)={ try { let xhr=new XMLHttpRequest();xhr.open('GET 'url,true);xhr.setRequestHeader('range 'bytes=$ { start }-$ { end } `);//请求头上设置范围请求信息xhr。响应类型=“数组缓冲区”;//设置返回的类型为数组缓冲区xhr。onload=function(){ resolve({ index:I,//文件块的索引buffer: xhr.response,//范围请求对应的数据});};xhr。send();} catch(err){ reject(new Error(err));} });}需要注意的是数组缓冲器对象用来表示通用的、固定长度的原始二进制数据缓冲区。
2.1.4定义concatenate函数由于ArrayBuffer对象不能直接操作,我们需要先将ArrayBuffer对象转换成Uint8Array对象,然后再进行合并操作。
下面定义的连接功能是合并下载的文件数据块。具体代码如下:
Function concatenate (array) {if (! Arrays.length) returns null. Set totalLength=arrays.reduce((acc, value)=acc value.length, 0); let result=new uint 8 array(total length); Let the length=0; For (array of let array) {result.set(array, length); Length=array.length} returns the result; }2.1.5 Define the saving mode function The saving mode function is used to realize the function of saving the client file.
函数saveAs({ name,buffers,mime=' application/octet-stream ' }){ const Blob=new Blob([buffers],{ type:mime });const blo burl=URL。createobjecturl(blob);const a=文档。createelement(' a ');a .下载=名称| |数学。random();a.href=blobUrla。单击();网址。revokeobjecturl(blob);}在保存方式函数中,
Blob:https://example.org/40A5FB5A-D56d-4A33-B4E2-0ACF6A8E5F641复制代码浏览器在内部为URL.createObjectURL生成的每个URL存储一个URL Blob映射
2.1.6定义下载功能。下载功能用于实现下载操作,它支持三个参数:
异步函数下载({ url,chunkSize,pool limit=1 }){ const contentLength=await get contentLength(URL);const chunks=chunkSize===' number '数学。ceil(contentLength/chunk size):1;const results=await异步池(池限制,[.新数组(块)。keys()],(I)={ let start=I * chunk size;let end=I 1==chunks内容长度-1:(I 1)* chunkSize-1;返回getBinaryContent(url,start,end,I);} );const sortedBuffers=results .map((item)=新的uint 8数组(item。缓冲));返回连接(排序的缓冲区);}2.2 大文件下载使用示例基于前面定义的辅助函数,
函数multithreaddownload(){ const URL=document。查询选择器(“#文件URL”).价值;如果(!网址||!/https /.测试(网址))返回;console.log('多线程下载开始:' new Date());下载({ url,chunkSize: 0.1 * 1024 * 1024,poolLimit: 6,}).然后((buffers)={ console.log('多线程下载结束:' new Date());另存为({缓冲区,名称:'我的压缩包,mime:' application/zip ' });});}由于完整的示例代码内容比较多,
完整的示例代码:https://要旨。github。com/SEM linker/837211 c 039 e 6311 E1 e 7629 e 5 ee 5 f 0 a 42
这里我们来看一下大文件下载示例的运行结果:
三、总结本文介绍了在JavaScript 中如何利用async-pool 这个库提供的asyncPool 函数,来实现大文件的并行下载。除了介绍asyncPool 函数之外,
阿宝哥还介绍了如何通过HEAD 请求获取文件大小、如何发起HTTP 范围请求及在客户端如何保存文件等相关知识。其实利用asyncPool 函数不仅可以实现大文件的并行下载,
而且还可以实现大文件的并行上传,感兴趣的小伙伴可以自行尝试一下。作者:阿宝哥链接:https://juejin.cn/post/6954868879034155022来源:掘金
标题:JavaScript 中如何实现大文件并行下载?
链接:https://www.52hkw.com/news/rj/69834.html
版权:文章转载自网络,如有侵权,请联系删除!