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標籤直接下載的。這樣是先彈出窗口,再利用瀏覽器的下載工具進行下載,雖然少了一些定製顯示,但用戶體驗上應該會好一點。 再找個下載文件的網站參考參考。前端

相關文章
相關標籤/搜索