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