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
相关产品推荐
相关产品推荐

