zoukankan      html  css  js  c++  java
  • 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标签直接下载的。这样是先弹出窗口,再利用浏览器的下载工具进行下载,虽然少了一些定制显示,但用户体验上应该会好一点。 再找个下载文件的网站参考参考。

  • 相关阅读:
    Bitnami Redmine安装和插件配置
    DataTable转换成List<T>
    学习Javascript闭包(Closure)
    单例模式(Singleton)
    哈希表--HashSet<T>
    .NET 4.0中的泛型的协变和逆变
    vue-cli脚手架里如何配置屏幕自适应
    新手如何理解JS面向对象开发?
    vue轮播图插件vue-awesome-swiper的使用与组件化
    vue中sass的配置安装流程
  • 原文地址:https://www.cnblogs.com/chengyunshen/p/11376735.html
Copyright © 2011-2022 走看看