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

Node.js脚本无法下载图片求助(Ubuntu 24.04 + Puppeteer)

问题描述

在Ubuntu 24.04系统上运行Node.js 22.13.1脚本,通过Puppeteer连接网站获取图片列表功能正常,但图片下载保存环节失效。采用常见的http.get+流写入方式,代码如下:

for(var x=0;x<card_arr.length;x++)
{
    var key = card_arr[x]
    const file = fs.createWriteStream(gp_args['local_path_start'] + '/' + key + '.jpg');
    console.log('getting ' + gp_args['local_path_start'] + '/' + key + '.jpg')
    console.log('from ' + gp_args['url'] + 'img/' + key + '.jpg')
    http.get(gp_args['url'] + 'img/' + key + '.jpg', res => {
        // Write data into local file
        res.pipe(file)

        // Close the file
        file.on('finish', () => {
          file.close()
          console.log(`File downloaded!`)
        })
    })
        .on('error', err => {
        console.log('Error: ', err.message)
    })

    var milliseconds = 300
    var waitTill = new Date(new Date().getTime() + milliseconds);
    while(waitTill > new Date()){}
}

脚本能正常打印下载路径和源链接,但本地目标文件夹为空,既无报错信息也无File downloaded!提示,且图片链接在浏览器中可正常访问。

排查与修改方案

1. 确保目标目录存在

fs.createWriteStream不会自动创建不存在的上级目录,如果gp_args['local_path_start']对应的目录(比如images/remotesite.com)不存在,写入操作会静默失败。在创建写入流前,先递归创建目录:

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

// 循环内替换原路径拼接和流创建代码
const savePath = path.join(gp_args['local_path_start'], `${key}.jpg`);
// 递归创建所有不存在的上级目录
fs.mkdirSync(path.dirname(savePath), { recursive: true });
const file = fs.createWriteStream(savePath);

2. 移除同步阻塞的等待逻辑

你用的while(waitTill > new Date()){}是同步阻塞代码,会完全占用Node.js的事件循环,导致HTTP请求的回调(包括响应、finish、error事件)根本无法执行。把同步等待改成异步等待,配合async/await重构循环:

async function downloadImages() {
  for(const key of card_arr) {
    const savePath = path.join(gp_args['local_path_start'], `${key}.jpg`);
    fs.mkdirSync(path.dirname(savePath), { recursive: true });
    const file = fs.createWriteStream(savePath);

    console.log('getting ' + savePath)
    console.log('from ' + gp_args['url'] + 'img/' + key + '.jpg')

    await new Promise((resolve, reject) => {
      http.get(gp_args['url'] + 'img/' + key + '.jpg', res => {
        // 检查响应状态码
        if (res.statusCode !== 200) {
          console.error(`请求图片失败 ${key}: 状态码 ${res.statusCode}`);
          res.resume();
          file.destroy();
          resolve(); // 跳过当前图片继续执行
          return;
        }

        res.pipe(file);

        file.on('finish', () => {
          file.close();
          console.log(`File downloaded! ${savePath}`);
          resolve();
        });

        file.on('error', err => {
          console.error(`写入文件失败 ${savePath}:`, err.message);
          file.destroy();
          reject(err);
        });
      })
      .on('error', err => {
        console.log('HTTP请求错误: ', err.message);
        file.destroy();
        reject(err);
      });
    });

    // 异步等待300ms
    await new Promise(resolve => setTimeout(resolve, 300));
  }
}

// 启动下载
downloadImages().catch(err => console.error('批量下载失败:', err));

3. 补充完整的错误监听

除了HTTP请求的错误,还要监听文件流的写入错误(比如权限不足、磁盘空间不足),同时检查HTTP响应的状态码,避免无效响应写入文件。

4. 检查目录权限

如果目标目录是系统级路径(比如/var/www),要确保运行Node.js的用户有该目录的读写权限,可通过sudo chown -R $USER:$USER ./images调整目录权限。

内容的提问来源于stack exchange,提问作者raphael75

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:30:02