- 使用常用的 axios 进行下载时,会遇到以下一些问题:
- 超时问题:如果下载的文件较大或网络连接较慢,可能会导致请求超时。
- 内存问题:如果下载的文件非常大,将整个文件存储在内存中可能会导致内存溢出,下载的文件会出现截断或损坏。
- 进度跟踪问题:axios 默认不提供下载进度的功能。需要使用 axios-progress-bar 等第三方库来实现下载进度的监控和显示。
- 下载文件时,需要等待整个文件流都下载到内存中才会弹出浏览器的下载文件保存对话框,用户体验较差。
- 使用Fetch下载相比Axios在文件下载方面的一些优势:
- 原生支持:Fetch是浏览器原生提供的API,不需要额外的第三方库或依赖。这意味着在现代浏览器中,无需额外配置即可直接使用Fetch进行文件下载。
- 内置的流支持:Fetch使用ReadableStream对象处理响应数据,这使得在下载大文件时能够有效地处理数据流,减少内存占用。相比之下,Axios默认将整个响应加载到内存中,对于大文件下载可能会导致内存问题。
- 下载响应开始就可以弹出浏览器下载保存对话框,并且不影响文件流下载,而axios需要等待整个文件流都下载到内存中才会弹出浏览器的下载文件保存对话框
- StreamSaver:StreamSaver.js 是一个用于在浏览器中实现流式文件下载的 JavaScript 插件。它提供了一种简单而强大的方式来下载大文件或流式数据,而无需将整个文件加载到内存中。
- 逐步下载:StreamSaver.js 通过逐步写入磁盘,实现了流式下载,避免了将整个文件加载到内存中
- 跨浏览器兼容性:StreamSaver.js 支持主流的现代浏览器,包括 Chrome、Firefox、Edge 和 Safari。
- 断点续传:通过在下载过程中保存已下载的部分,StreamSaver.js 支持断点续传,即使在网络中断或下载过程中停止,也可以从上次中断的地方恢复下载。
npm install streamsaver
import * as StreamSaver from "streamsaver";
...
const url = '/api/downloadFile?address=xxxxx'
const filename = `xxxxx.xxx`;
const fileStream = StreamSaver.createWriteStream(filename);
fetch(url, {
method: 'GET',
cache: 'no-cache',
headers: {
'xxxx': 'xxxx'
}
}).then(res => {
const readableStream = res.body
// more optimized
if (window.WritableStream && readableStream.pipeTo) {
return readableStream.pipeTo(fileStream)
.then(() => console.log('done writing'))
}
window.writer = fileStream.getWriter()
const reader = res.body.getReader()
const pump = () => reader.read()
.then(res => res.done
? window.writer.close()
: window.writer.write(res.value).then(pump))
pump()
})