vue实现大文件下载
使用分片下载实现大文件下载
在Vue中实现大文件下载,可以采用分片下载的方式,避免内存溢出和网络中断问题。以下是具体实现方法:
安装axios库:

npm install axios
创建下载工具函数:
import axios from 'axios';
export function downloadLargeFile(url, fileName, chunkSize = 1024 * 1024) {
const controller = new AbortController();
axios({
url,
method: 'HEAD',
signal: controller.signal
}).then(response => {
const totalSize = response.headers['content-length'];
const totalChunks = Math.ceil(totalSize / chunkSize);
const promises = [];
for (let i = 0; i < totalChunks; i++) {
const start = i * chunkSize;
const end = Math.min(start + chunkSize - 1, totalSize - 1);
promises.push(
axios.get(url, {
headers: { Range: `bytes=${start}-${end}` },
responseType: 'blob'
})
);
}
return Promise.all(promises);
}).then(chunks => {
const blob = new Blob(chunks.map(chunk => chunk.data));
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = fileName;
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(downloadUrl);
document.body.removeChild(link);
}).catch(error => {
if (error.name !== 'AbortError') {
console.error('下载失败:', error);
}
});
return controller;
}
显示下载进度
添加进度显示功能可以提升用户体验:

export function downloadWithProgress(url, fileName, onProgress) {
return new Promise((resolve, reject) => {
axios({
url,
method: 'GET',
responseType: 'blob',
onDownloadProgress: progressEvent => {
if (onProgress) {
const percent = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
onProgress(percent);
}
}
}).then(response => {
const blob = new Blob([response.data]);
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = fileName;
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(downloadUrl);
document.body.removeChild(link);
resolve();
}).catch(reject);
});
}
断点续传实现
对于超大文件,实现断点续传功能:
export function resumeDownload(url, fileName, savedChunks = []) {
const controller = new AbortController();
axios({
url,
method: 'HEAD',
signal: controller.signal
}).then(response => {
const totalSize = response.headers['content-length'];
const downloadedSize = savedChunks.reduce((sum, chunk) => sum + chunk.size, 0);
if (downloadedSize >= totalSize) {
const blob = new Blob(savedChunks);
// 触发下载
return;
}
const remainingSize = totalSize - downloadedSize;
const chunkSize = 1024 * 1024; // 1MB
const totalChunks = Math.ceil(remainingSize / chunkSize);
const promises = [];
for (let i = 0; i < totalChunks; i++) {
const start = downloadedSize + i * chunkSize;
const end = Math.min(start + chunkSize - 1, totalSize - 1);
promises.push(
axios.get(url, {
headers: { Range: `bytes=${start}-${end}` },
responseType: 'blob'
}).then(res => {
savedChunks.push(res.data);
return res.data.size;
})
);
}
return Promise.all(promises);
}).then(() => {
const blob = new Blob(savedChunks);
// 触发下载
}).catch(error => {
console.error('下载失败:', error);
});
return controller;
}
在Vue组件中使用
在Vue组件中调用下载功能:
<template>
<div>
<button @click="startDownload">下载大文件</button>
<div v-if="progress > 0">
下载进度: {{progress}}%
</div>
</div>
</template>
<script>
import { downloadWithProgress } from './downloadUtils';
export default {
data() {
return {
progress: 0
};
},
methods: {
startDownload() {
const url = 'https://example.com/large-file.zip';
const fileName = 'large-file.zip';
downloadWithProgress(url, fileName, (percent) => {
this.progress = percent;
}).then(() => {
this.$message.success('下载完成');
}).catch(() => {
this.$message.error('下载失败');
});
}
}
};
</script>
注意事项
- 服务器必须支持Range请求头才能实现分片下载
- 大文件下载会占用较多内存,建议分片大小根据实际情况调整
- 断点续传需要本地存储已下载的分片数据
- 考虑添加下载取消功能,避免资源浪费
这些方法可以根据实际需求组合使用,实现稳定可靠的大文件下载功能。






