問題描述
- 使用axios發請求,想要實現一個請求的結果進度
- 比如當網路慢的情況,或者某個請求返回的資料量比較大的情況等
- 最常見的就是下載一個大檔案,要檢視大檔案下載的進度
- axios的onDownloadProgress函式已經幫我們封裝好了
- 是基於原生的ProgressEvent套殼子的
比如我們下載一個流檔案,要呈現下載的進度,在這裡列印一下進度事件
axios({
method: "get",
responseType: "blob", // 流檔案為blob型別
url: "http://ashuai.work:10000/getDoc",
onDownloadProgress(ProgressEvent) {
console.log('進度事件', ProgressEvent);
}
}).then(({ data }) => {
console.log('介面請求完成',data);
});
列印結果如下圖:
這裡為何拿不到total的值?
- 是因為介面的響應頭,沒有返回Content-Length屬性
- 所以ProgressEvent就拿不到這個值,所以就沒有total的值,就為undefined
請看響應頭
Content-Length 大家可以簡要理解成為一個介面返回的內容的總大小,單位位元組,我們知道了某個時刻loaded多少位元組,知道總位元組,就可以得出百分比了
解決方案
讓後端在響應頭上加上Content-Length即可
讓後端在響應頭上加上Content-Length即可
讓後端在響應頭上加上Content-Length即可
筆者這裡使用express演示一下程式碼:
route.get('/getDoc', (req, res) => {
res.header('Access-Control-Allow-Origin', '*');
// fs.statSync讀取檔案資訊,讀取當前目錄下的study.docx檔案
let docxUrl = './doc/study.docx'
const Myfilesize = fs.statSync(docxUrl).size // 拿到檔案位元組大小
// 設定請求頭
res.writeHead(200, {
'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'content-length': Myfilesize // 加上即可
})
let readStream = fs.createReadStream(docxUrl) // 流檔案pipe管道返回
readStream.pipe(res);
})
加上以後,響應頭就有Content-Length了,就能正常了
這樣的話,進度條效果也就有了
流檔案請求手動加上,普通的請求會自帶Content-Length的
程式碼附上
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.5/axios.js"></script>
<title>請求介面進度</title>
</head>
<body>
<button @click="goPreview">點選預覽word檔案</button>
<br>
<progress max="100" value="0"></progress> <span class="val">0</span>
<script>
let btn = document.querySelector('button')
let prog = document.querySelector('progress')
let v = document.querySelector('.val')
btn.onclick = () => {
axios({
method: "get",
responseType: "blob", // 流檔案為blob型別
url: "http://ashuai.work:10000/getDoc",
onDownloadProgress(ProgressEvent) {
let percent = Math.floor((ProgressEvent.loaded / ProgressEvent.total) * 100)
prog.setAttribute('value', percent)
v.innerHTML = percent + '%'
console.log('進度事件', ProgressEvent);
}
}).then(({ data }) => {
console.log(data); // 後端返回的是流檔案
});
}
</script>
</body>
</html>