浩克网 手游攻略 软件教程 六步实现JavaScript大型文件并行下载?

六步实现JavaScript大型文件并行下载?

时间:2026-07-01 09:17:39 来源:网络整理 浏览:0

大家好,很高兴再次见到大家。我是‘高级前端高级’。我带你关注前端前沿,深入前端底层技术。我们会一起进步。也欢迎您的关注、赞、收藏和转发!

高级前端高级

前言相信有些小伙伴已经了解了上传大文件的解决方案。上传大文件时,为了提高上传效率,一般采用Blob.slice方法,将大文件按照指定的大小进行切割,然后启动多线程分块上传。

所有块上传成功后,通知服务器合并块。

var blob=instanceofblob . slice([start[,end [,content type]]};注意:某些浏览器和版本中有厂商前缀:例如Firefox 12及更早版本中的blob.mozSlice()和旧版的blob.webkitSlice()。Safari中的slice()方法。

那么,下载大文件可以采用类似的思路吗?在服务器支持范围请求头的情况下,也可以实现多线程块下载功能,如下图所示:

看了上图,相信对下载大文件的方案有了一定的了解。接下来,我们先介绍一下HTTP范围请求。

1.HTTP范围请求HTTP协议范围请求允许服务器只向客户端发送HTTP消息的一部分。在传输大型媒体文件或与文件下载的断点续传功能一起使用时,范围请求非常有用。

如果响应中有Accept-Ranges标头(并且其值不是“none”),则意味着服务器支持范围请求。在范围标题中,可以一次请求多个零件。

服务器将把它作为一个多部分文件返回。如果服务器返回范围响应,您需要使用206部分内容状态代码。如果请求的范围不合法,

则服务器将返回416范围不可满足状态代码,指示客户端错误。服务器允许忽略范围头,从而返回整个文件,状态码为200。

单一Range curl https://www . Baidu . com/img/PCtm _ d 9 c 8750 bed 0 b 3c 7d 089 fa 7d 55720 D6 cf . png-I-H ' Range:bytes=0-1023 ' Export is wie folgt:

Multiple rangecurl http://www.baidu.com-i-h' range: bytes=0-50,100-150' output results are as follows:

2 HTTP范围大文件下载2.1定义辅助函数2.1.1 getContentLength函数顾名思义,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异步池函数异步池函数用于实现异步任务的并发控制。

异步函数asyncPool(poolLimit,array,iterator fn){ const ret=[];//存储所有的异步任务const executing=[];//存储正在执行的异步任务对于(数组的常量项){ const p=Promise.resolve().然后(()=iteratorFn(item,array));ret。推(p);if(池限制=数组。length){ const e=p . then(()=正在执行。拼接(正在执行。(e),1)的索引;正在执行。推(e);如果(正在执行。长度=池限制){//等待较快的任务执行完成等待承诺正在执行);} } }返回保证。所有(ret);}2.1.3 getBinaryContent函数getBinaryContent函数用于根据传入的参数发起范围请求,

函数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,//Range请求对应的数据});};xhr。send();} catch(err){ reject(new Error(err));} });}需要注意的是:数组缓冲区对象用来表示通用的、固定长度的原始二进制数据缓冲区。

2.1.4 concatenate 函数由于不能直接操作ArrayBuffer 对象,所以需要先把ArrayBuffer 对象转换为Uint8Array 对象,然后在执行合并操作。

以下定义的concatenate 函数就是为了合并已下载的文件数据块,具体代码如下所示:

function concatenate(arrays) { if (!arrays.length) return null; let totalLength=arrays.reduce((acc, value)=acc + value.length, 0); let result=new Uint8Array(totalLength); let length=0; for (let array of arrays) { result.set(array, length); length +=array.length; } return result;}2.1.5 saveAs 函数saveAs 函数用于实现客户端文件保存的功能,

function saveAs({ name, buffers, mime='application/octet-stream' }) { const blob=new Blob([buffers], { type: mime }); //创建Blob const blobUrl=URL.createObjectURL(blob); //实例化 const a=document.createElement('a'); a.download=name || Math.random(); a.href=blobUrl; a.click(); URL.revokeObjectURL(blob);}在saveAs 函数中,

blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641浏览器内部为每个通过URL.createObjectURL 生成的URL 存储了一个URL Blob 映射。

2.1.6 定义download 函数download 函数用于实现下载操作,它支持3 个参数:

单位为字节poolLimit(数字类型):表示限制的并发数async function download({ url, chunkSize, poolLimit=1 }) { const contentLength=await getContentLength(url); const chunks= typeof chunkSize==='number' Math.ceil(contentLength/chunkSize) : 1; const results=await asyncPool( poolLimit, [.new Array(chunks).keys()], (i)={ let start=i * chunkSize; let end=i + 1==chunks contentLength - 1 : (i + 1) * chunkSize - 1; return getBinaryContent(url, start, end, i); } ); const sortedBuffers=results.map((item)=new Uint8Array(item.buffer)); return concatenate(sortedBuffers);}2.2 大文件下载使用示例基于定义的辅助函数,

function multiThreadedDownload() { const url=document.querySelector('#fileUrl').value; if (!url || !/https /.test(url)) return; console.log('multi threaded download start: ' + +new Date()); download({ url, chunkSize: 0.1 * 1024 * 1024, poolLimit: 6, }).then((buffers)={ console.log('multi threaded download end: ' + +new Date()); saveAs({ buffers, name: 'myzip', mime: 'application/zip' }); });}完整代码请查看文末参考文献。

3.总结本文介绍了在JavaScript 中如何利用async-pool 这个库提供的asyncPool 函数来实现大文件的并行下载。除了介绍asyncPool 函数之外,

文章还介绍了如何通过HEAD 请求获取文件大小、如何发起HTTP Range 请求及在客户端如何保存文件等相关知识。其实利用asyncPool 函数不仅可以实现大文件的并行下载,

而且还可以实现大文件的并行上传,感兴趣的小伙伴可以自行尝试一下。

参考资料https://blog.bitsrc.io/implement-concurrent-download-of-large-files-in-javascript-4e94202c5373

https://github.com/eligrey/FileSaver.js

https://mp.weixin.qq.com/s/lQKTCS_QB0E62SK9oXD4LA

https://gist.github.com/semlinker/837211c039e6311e1e7629e5ee5f0a42

https://juejin.cn/post/69548688790341

https://developer.mozilla.org/zh-CN/docs/Web/API/Blob/slice

标题:六步实现JavaScript大型文件并行下载?
链接:https://www.52hkw.com/news/rj/69832.html
版权:文章转载自网络,如有侵权,请联系删除!
资讯推荐
更多
Tiktok专用的梯子加速器(TK加速器全球加速)

Tiktok作为当前最火爆的短视频平台,受到了全球用户的热烈欢迎。然而,由于网络限制或者其他原因,很多用户在观看

2026-07-01
怎么不让快递放菜鸟驿站

菜鸟裹裹怎么禁止放快递?经常网购的小伙伴都知道,如果附近有菜鸟驿站,那么驿站的快递员会默认选择放在驿站中,并

2026-07-01
德国游戏排行榜前十名(德国出品的游戏)

中国的玩家可能在新闻里听过德国科隆游戏展,但对德国的游戏却感觉很陌生。游戏玩家大部分多少应该都体验过SL

2026-07-01
天国的姉弟のカンケイ四部合集(弹丸论破a1处刑合集)

Spike Chunsoft公布了《弹丸论破》四部合集《弹丸论破 三部曲合集+幸福弹丸论破S 超高中级的南国掷骰合宿》

2026-07-01