fetch的文件流下载及下载进度获取

  • 下载过程中,获取进度,fetch API并没有提供类似xhr和ajax的 progress所以用 getReader()来循环读取大小
     let  size = 0;
          fetch( URL() + `/sys/file/download/${uuid}`,{
            method: 'GET',
            headers:{
                token,
            }
        })
        .then(response => {
            if(response.ok){
                return response;
            }else{
                console.log("请求失败")
            }
        })
            // 取出body
            .then(response => response.body)
            .then(body => {
              const reader = body.getReader();

                  return new ReadableStream({
                    start(controller) {
                      return pump();

                      function pump() {
                        return reader.read().then(res => {   //res  ({ done, value }) 
                          // 读不到更多数据就关闭流
                          console.log(res,"res");
                          const {done,value } = res;
                          if (done) {
                              console.log("end")
                            controller.close();
                            // return;
                          }
                            size += value.length  || 0;
                            console.log(size,"size")
                          // 将下一个数据块置入流中
                          controller.enqueue(value);
                          return pump();
                        });
                      }
                    }
                  })
                })
                .then(stream => new Response(stream))
                .then(response => that.savingFile(response,fileName))
                .catch(err => console.error(err));
  • 上一步中接收到文件流后,通过Blob和a标签进行下载
 savingFile = (response,fileName) => {
         const that = this;
         response.blob().then( blob => {     
            if(typeof FileReader === 'undefined'){
                notification.open({
                     message:'您的浏览器不支持 FileReader,请升级浏览器',
                     icon: <Icon type="smile" style={{ color: '#108ee9' }} />
                })
            }
            const reader = new FileReader();                                    
            reader.addEventListener("loadend", function() {     
                        let resu = '';
                        try{
                            resu = JSON.parse( reader.result);
                             // resu = eval('('+ reader.result + ')')
                            if(resu.code == 500){
                                notification.open({
                                     message:resu.msg,
                                      icon: <Icon type="smile" style={{ color: '#108ee9' }} />
                                })
                            }else if(resu.code == 401){
                                notification.error({
                                     message:resu.msg
                                })
                            }
                        }catch(e){
                            //捕获错误 说明是文本字符串 
                            resu = reader.result;
                            downloadBlob(blob,fileName);
                        }
                    
            });
            reader.readAsText(blob);    
                 
                 //下载
                 function downloadBlob(blob,fileName){
                        let blobUrl = window.URL.createObjectURL(blob);
                        let a = document.createElement('a');
                        a.href = blobUrl;
                        a.target = '_blank';
                        a.style.display = 'none'
                        document.body.appendChild(a)
                        a.download = fileName;
                        a.click();
                        window.URL.revokeObjectURL(blobUrl);
                        document.body.removeChild(a)
                        
                        that.setState({
                            downloading:false
                        })
                 }
         })
     }

总结一下: 这种前端下载的方式,感觉体验还不是很好。主要考虑是文件流的下载方式,是先下载完全部数据才弹出保存窗口,而大部分软件下载的网站是用a标签直接下载的。这样是先弹出窗口,再利用浏览器的下载工具进行下载,虽然少了一些定制显示,但用户体验上应该会好一点。 再找个下载文件的网站参考参考。

上一篇:Greendao


下一篇:WPF程序最小化至系统托盘