NodeJS实现RSS Feed MP3文件逐个下载及进度追踪方案
NodeJS RSS音频串行下载与进度追踪实现
问题背景
原脚本通过Promise.all同时触发所有音频文件的下载,会占用大量带宽;需要修改为逐个串行下载,并添加下载进度百分比显示功能。
优化后完整代码
const https = require('https'); const xml2js = require('xml2js'); const parser = new xml2js.Parser(); const fs = require('fs'); const path = require('path'); const URL_TO_PARSE = 'https://some-rss.feed.xml'; // 处理文件名中的非法字符 const sanitizeFilename = (filename) => { return filename.replace(/[<>:"/\\|?*]/g, '_'); }; const downloadAudioFile = async (url, filepath) => { return new Promise((resolve, reject) => { https.get(url, (res) => { // 处理HTTP错误状态码 if (res.statusCode !== 200) { reject(new Error(`请求失败,状态码:${res.statusCode}`)); return; } const totalSize = parseInt(res.headers['content-length'], 10); let downloadedSize = 0; const writeStream = fs.createWriteStream(filepath); res.on('data', (chunk) => { downloadedSize += chunk.length; // 计算并实时打印进度百分比 const progress = ((downloadedSize / totalSize) * 100).toFixed(2); process.stdout.write(`\r下载进度:${progress}%`); }); res.pipe(writeStream); writeStream.on('finish', () => { writeStream.close(); process.stdout.write('\n'); // 换行避免覆盖后续输出 console.log(`${path.basename(filepath)} 下载完成`); resolve(); }); writeStream.on('error', (err) => { fs.unlinkSync(filepath); // 下载失败删除不完整文件 reject(err); }); res.on('error', (err) => { reject(err); }); }).on('error', (err) => { reject(err); }); }); }; const main = async () => { try { // 获取并解析RSS Feed const xml = await new Promise((resolve, reject) => { https.get(URL_TO_PARSE, (res) => { let data = ''; res.on('data', (chunk) => data += chunk); res.on('end', () => resolve(data)); res.on('error', reject); }).on('error', reject); }); const result = await parser.parseStringPromise(xml); const items = result.rss.channel[0].item; // 串行遍历下载,逐个执行 for (const item of items) { const title = item.title[0]; const enclosure = item.enclosure[0]; const url = enclosure.$.url; // 处理文件名并添加.mp3后缀 const safeFilename = sanitizeFilename(title); const filepath = `./${safeFilename}.mp3`; console.log(`开始下载:${title}`); await downloadAudioFile(url, filepath); console.log('---'); } console.log('所有文件下载完成'); } catch (err) { console.error('执行出错:', err); } }; main();
关键改动说明
- 串行下载实现:将原
Promise.all(items.map(...))改为for...of循环配合await,确保每个文件下载完成后才启动下一个任务。 - 进度追踪功能:
- 从响应头
content-length获取文件总大小 - 监听
data事件累计已下载字节数,计算百分比 - 使用
process.stdout.write('\r')实现同一行覆盖输出,避免进度刷屏
- 从响应头
- Promise封装修复:将
downloadAudioFile正确封装为Promise,确保await能正确等待下载完成 - 额外优化:
- 添加文件名非法字符处理,避免写入文件失败
- 增加HTTP错误状态码判断,下载失败时自动删除不完整文件
- 统一使用
async/await替代嵌套回调,提升代码可读性 - 强制添加
.mp3后缀,确保文件格式正确
内容的提问来源于stack exchange,提问作者CoderPadwan
相关产品推荐
相关产品推荐

