You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:54:20