获取blob javascript的进度

获取blob javascript的进度,javascript,fetch,blob,Javascript,Fetch,Blob,我正在尝试使用fetch进行javascript获取以获取视频文件。我可以下载文件并获得blob URL,但在下载过程中我似乎无法获得进度 我试过这个: let response = await fetch('test.mp4'); const reader = response.body.getReader(); const contentLength=response.headers.get('Content-Length');

我正在尝试使用fetch进行javascript获取以获取视频文件。我可以下载文件并获得blob URL,但在下载过程中我似乎无法获得进度

我试过这个:

    let response = await fetch('test.mp4');
    
    const reader = response.body.getReader();
    
    const contentLength=response.headers.get('Content-Length');
    
    let receivedLength = 0; 
    d=document.getElementById('progress_bar');
    while(true) 
    {
        const {done, value} = await reader.read();
        
        if (done) 
        {
            break;
        }
        receivedLength += value.length;
        d.innerHTML="Bytes loaded:"+receivedLength;
    }
    
    const blob = await response.blob();
    
    var vid=URL.createObjectURL(blob);
问题是我得到了“Response.blob:Body已经被消耗了”。我看到reader.read()可能正在这样做。如何获取接收到的数据量,然后在其末尾获取blob URL


谢谢。

更新:

我的第一次尝试是在下载时收集数据块,然后将它们重新组合在一起,占用大量内存(视频大小的2-3倍)。使用ReadableStream的内存占用要小得多(对于1.1GB的mkv,内存使用量徘徊在150MB左右)。代码大部分改编自此处的代码片段,仅对我进行了少量修改:


const elProgress=document.getElementById('progress\u bar'),
player=document.getElementById('video_player');
函数getVideo2(){
让contentType='video/mp4';
获取(“$pathToVideo.mp4”)
。然后(响应=>{
const contentEncoding=response.headers.get('content-encoding');
const contentLength=response.headers.get(contentEncoding?'x-file-size':'content-length');
contentType=response.headers.get('content-type')| | contentType;
if(contentLength==null){
抛出错误(“响应大小标头不可用”);
}
const total=parseInt(contentLength,10);
设加载=0;
返回新的响应(
新的ReadableStream({
启动(控制器){
const reader=response.body.getReader();
read();
函数read(){
reader.read().then({done,value})=>{
如果(完成){
controller.close();
返回;
}
加载+=值。通过TELENGTH;
进度({已加载,总计})
控制器排队(值);
read();
}).catch(错误=>{
控制台错误(error);
控制器错误(错误)
})
}
}
})
);
})
.then(response=>response.blob())
.然后(blob=>{
设vid=URL.createObjectURL(blob);
player.style.display='block';
player.type=contentType;
player.src=vid;
elProgress.innerHTML+=“
按播放!”; }) .catch(错误=>{ 控制台错误(error); }) } 函数进度({已加载,总计}){ elProgress.innerHTML=Math.round(已加载/总计*100)+'%'; }
第一次尝试(更糟,适用于较小的文件)

我最初的方法。对于1.1GB的mkv,在下载文件时内存使用量会逐渐增加到1.3GB,然后在组合块时会增加到3.5Gb左右。一旦视频开始播放,该标签的内存使用量将下降到~200MB,但Chrome的总体使用量仍保持在1GB以上

与调用
response.blob()
获取blob不同,您可以通过累加视频的每个块(
value
)来构建blob。此处改编自exmaple:

/。。。
receivedLength+=value.length;
推送(值);
//...
//==>将区块放入Blob构造函数可以使用的UINT8数组中
让Uint8Chunks=newuint8array(receivedLength),位置=0;
for(让块中的块){
Uint8Chunks.set(块,位置);
位置+=chunk.length;
}
//==>您可能希望从内容类型头中获取mimetype
const blob=新blob([Uint8Chunks],{type:'video/mp4'})

哪一行抛出此错误?@ggorlen这是行
const blob=wait response.blob()这看起来可以解决问题,但这不需要使用更多的资源吗?这个项目的视频将是2GB+的,因此它将在块上使用2GB存储空间+2GB存储空间。“有没有一种方法不会占用更多的存储空间?”ChimpKey说得很好,我最初的答案是内存占用,峰值约为视频大小的3倍。我发现了一种效果更好的方法。我流了一个1.1GB的视频,内存使用量保持在150MB左右。非常感谢。很有帮助。@ ChimpKey,如果这解决了你的问题,考虑接受这个答案,让未来的观众知道这个答案解决了。issue@ChimpKey谢谢我学习了很多关于
获取
的研究。