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

如何在Node.js中当文件小于1KB时终止下载并尝试下一个URL

文件下载失败自动重试下一个URL的实现方案

需求说明

使用Node.js的https模块下载文件时,若目标URL不存在,模块不会抛出错误,只会生成一个1字节的run.jar文件。需要实现:下载完成后检测文件大小,若小于1KB则终止当前后续代码执行,自动尝试downloadurl数组中的下一个URL。

原始代码

const downloadurl = ['url1', 'url2']
const filename = 'run.jar'

downloadurl.forEach((urls) => {
    https.get(urls, (httpsres) => {
        const path = `${installationdirectory}/${filename}`
        const filePath = fs.createWriteStream(path);
        httpsres.pipe(filePath);
        filePath.on('finish',() => {

            filePath.close();
            const filesize = fs.statSync(path).size
            // 校验文件大小是否小于1KB
            if((filesize / 1024) < 1) return;

            // 希望文件小于1KB时跳过此日志,尝试下一个URL
            console.log('File downloaded!'); 


        })
    })
})

问题分析

原始代码用forEach遍历URL,会同时发起所有请求,无法实现“失败后再试下一个”的串行逻辑。必须改成串行处理,逐个尝试URL,直到下载成功(文件大小符合要求)为止。

解决方案

1. 封装下载校验函数

把下载和文件校验逻辑封装成返回Promise的异步函数,方便串行调用:

const https = require('https');
const fs = require('fs');
const path = require('path');

const downloadurl = ['url1', 'url2'];
const filename = 'run.jar';
const installationdirectory = './downloads'; // 替换为你的实际路径

// 封装下载并校验的异步函数
async function downloadAndCheck(url) {
    return new Promise((resolve, reject) => {
        const filePath = path.join(installationdirectory, filename);
        
        // 发起请求
        https.get(url, (res) => {
            // 提前判断响应状态码,避免下载无效内容
            if (res.statusCode >= 400) {
                res.resume(); // 消耗响应体,避免内存泄漏
                return resolve(false);
            }

            const writeStream = fs.createWriteStream(filePath);
            
            // 处理文件写入错误
            writeStream.on('error', (err) => {
                console.error(`写入文件失败: ${err.message}`);
                writeStream.destroy();
                resolve(false);
            });

            // 下载完成后校验文件大小
            writeStream.on('finish', () => {
                try {
                    const stats = fs.statSync(filePath);
                    const fileSizeKB = stats.size / 1024;
                    // 大小>=1KB则认为下载成功
                    resolve(fileSizeKB >= 1);
                } catch (err) {
                    console.error(`读取文件信息失败: ${err.message}`);
                    resolve(false);
                }
            });

            res.pipe(writeStream);
        }).on('error', (err) => {
            console.error(`请求URL失败: ${err.message}`);
            resolve(false);
        });
    });
}

2. 串行遍历URL数组

用async/await循环遍历URL,逐个尝试,直到成功为止:

async function tryDownloads() {
    for (const url of downloadurl) {
        console.log(`尝试下载: ${url}`);
        const success = await downloadAndCheck(url);
        
        if (success) {
            console.log('文件下载成功!');
            break; // 成功则终止循环,不再尝试后续URL
        } else {
            console.log(`下载失败,尝试下一个URL`);
            // 可选:删除无效的小文件,避免残留垃圾
            try {
                fs.unlinkSync(path.join(installationdirectory, filename));
            } catch (err) {
                console.error(`删除无效文件失败: ${err.message}`);
            }
        }
    }
}

// 启动下载流程
tryDownloads().catch((err) => {
    console.error(`下载流程出错: ${err.message}`);
});

关键说明

  • 串行处理:用for...of配合await实现逐个请求,确保上一个请求处理完成后才尝试下一个。
  • 提前校验状态码:在响应阶段先判断状态码,避免下载404等无效响应体。
  • 全流程错误捕获:覆盖请求、文件写入、文件信息读取等环节的错误,确保流程不中断。
  • 清理无效文件:下载失败后自动删除小文件,避免磁盘垃圾。

内容的提问来源于stack exchange,提问作者Martín Rubina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:35:20