// Vue3 Composition API
import { ref, reactive, onMounted, onUnmounted } from 'vue';
import axios from 'axios';
export default {
setup() {
// 状态变量
const fileUrl = ref(''); // 文件URL
const currentStart = ref(0); // 当前下载的起始位置(字节)
const totalSize = ref(0); // 总文件大小(字节)
const downloadedSize = ref(0); // 已经下载的文件大小(字节)
const isDownloading = ref(false); // 是否正在下载
const downloadProgress = ref(0); // 下载进度(百分比)
const chunks = reactive([]); // 存储已下载的文件分片信息
// 方法
const startDownload = async () => {
isDownloading.value = true;
try {
while (currentStart.value < totalSize.value && isDownloading.value) {
// 设置请求Header中的Range字段
const end = Math.min(currentStart.value + chunkSize - 1, totalSize.value - 1);
const config = {
headers: {
Range: `bytes=${currentStart.value}-${end}`,
},
};
// 发送带Range头的GET请求
const response = await axios.get(fileUrl.value, config);
// 如果成功获取部分数据
if (response.status === 206) {
// 存储下载的分片
chunks.push({ start: currentStart.value, data: response.data });
// 更新下载位置和已下载大小
currentStart.value += response.data.byteLength;
downloadedSize.value += response.data.byteLength;
// 计算下载进度
downloadProgress.value = Math.floor((downloadedSize.value / totalSize.value) * 100);
// 检查是否下载完毕
if (currentStart.value >= totalSize.value) {
// 执行文件合并逻辑并结束下载
mergeAndDownload(chunks);
isDownloading.value = false;
return;
}
} else {
console.error('Failed to fetch file chunk');
break;
}
}
} catch (error) {
console.error('Error during download:', error);
isDownloading.value = false;
}
};
const pauseDownload = () => {
isDownloading.value = false;
};
const resumeDownload = async () => {
// 从上次暂停的地方开始下载
isDownloading.value = true;
startDownload();
};
// 获取总文件大小
const fetchTotalFileSize = async () => {
// 使用HEAD请求获取Content-Length
const response = await axios.head(fileUrl.value);
totalSize.value = parseInt(response.headers['content-length'], 10);
};
// 合并Blob分片为完整文件并提供下载
const mergeAndDownload = chunks => {
const blobParts = chunks.map(chunk => new Blob([chunk.data]));
const fullBlob = new Blob(blobParts, { type: 'application/octet-stream' });
const url = URL.createObjectURL(fullBlob);
const link = document.createElement('a');
link.href = url;
link.download = 'filename.ext'; // 替换为实际的文件名
document.body.appendChild(link);
link.click();
setTimeout(() => {
document.body.removeChild(link);
URL.revokeObjectURL(url);
}, 0);
};
// 生命周期钩子
onMounted(async () => {
// 先获取总文件大小
await fetchTotalFileSize();
// 初始化或恢复下载
if (/* 恢复下载条件 */) {
resumeDownload();
}
});
onUnmounted(() => {
// 清理资源(如有必要)
});
return {
startDownload,
pauseDownload,
resumeDownload,
downloadProgress,
};
},
};
大文件下载、暂停、继续下载
于 2024-03-29 10:35:45 首次发布