为了达到最佳效果,可以结合使用并发控制和分批加载文件的方法。这样既可以限制同时进行的下载任务数量,又可以逐步加载文件,进一步减轻服务器的压力。
1、普通多文件下载
const filesToDownload = [
{ url: 'https://example.com/file1.pdf', name: 'file1.pdf' },
{ url: 'https://example.com/file2.pdf', name: 'file2.pdf' },
{ url: 'https://example.com/file3.pdf', name: 'file3.pdf' }
];
const downloadFile = async (file) => {
try {
// 1. 发送 HTTP 请求获取文件数据
const response = await fetch(file.url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
// 2. 将响应数据转换为 Blob 对象
const blob = await response.blob();
// 3. 创建对象 URL
const url = URL.createObjectURL(blob);
// 4. 创建隐藏的 <a> 元素并设置属性
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = file.name;
// 5. 将 <a> 元素添加到文档中
document.body.appendChild(a);
// 6. 触发点击事件以启动下载
a.click();
// 7. 移除 <a> 元素
document.body.removeChild(a);
// 8. 释放对象 URL
URL.revokeObjectURL(url);
console.log(`${file.name} 下载完成`);
} catch (error) {
console.error(`下载 ${file.name} 失败:`, error);
}
};
const downloadAllFiles = async () => {
const promises = filesToDownload.map(downloadFile);
await Promise.all(promises);
console.log('所有文件下载完成');
};
downloadAllFiles();
2、文件数量过多,需要控制并发数场景
const axios = require('axios');
const files = Array.from({ length: 1000 }, (_, i) => `file${i}.txt`);
const batchSize = 10; // 每批下载的文件数
const maxConcurrency = 5; // 每批的最大并发数
async function downloadFile(file) {
const response = await axios.get(`https://example.com/api/download/${file}`);
// 处理下载的文件
console.log(`Downloaded ${file}`);
}
async function downloadFilesWithConcurrency(files, maxConcurrency) {
const pendingPromises = [];
for (const file of files) {
const promise = downloadFile(file).then(() => {
// 从待处理的 Promise 列表中移除已完成的 Promise
pendingPromises.splice(pendingPromises.indexOf(promise), 1);
});
// 将新的 Promise 添加到待处理的 Promise 列表中
pendingPromises.push(promise);
// 如果待处理的 Promise 数量达到最大并发数,则等待其中一个完成
if (pendingPromises.length >= maxConcurrency) {
await Promise.race(pendingPromises);
}
}
// 等待所有剩余的 Promise 完成
await Promise.all(pendingPromises);
}
async function downloadFilesInBatches(files, batchSize, maxConcurrency) {
for (let i = 0; i < files.length; i += batchSize) {
const batch = files.slice(i, i + batchSize);
await downloadFilesWithConcurrency(batch, maxConcurrency);
}
}
downloadFilesInBatches(files, batchSize, maxConcurrency);
总结: 通过结合使用并发控制和分批加载文件的方法,可以更有效地优化大量文件同时下载的情况,减少服务器的压力,提高系统的稳定性和性能。选择合适的策略取决于具体的业务需求和技术栈。