- 下载过程当中,获取进度,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标签直接下载的。这样是先弹出窗口,再利用浏览器的下载工具进行下载,虽然少了一些定制显示,但用户体验上应该会好一点。 再找个下载文件的网站参考参考。前端