使用NodeJS和async.queue下载并将大量图像保存到本地磁盘

时间:2015-07-06 00:26:06

标签: node.js asynchronous download

好的我有一个NodeJS应用程序,我正在尝试从Web服务器下载大量图像(现在大约500个,但数量会增加)。我得到的问题是“管道错误:EMFILE中的未处理的流错误”,因为似乎同时打开了太多的文件。

所以我试图使用async.queue来处理20批次的文件。但我仍然得到错误。

SomeModel.find({}, function(err, photos){
    if (err) {
        console.log(err);
    }
    else {

        photos.forEach(function(photo){

            var url = photo.PhotoURL;
            var image = url.replace('http://someurl.com/media.ashx?id=', '').replace('&otherstuffattheend', '.jpg');
            photo.target = image;

            var q = async.queue(function (task) {
                request
                    .get(task.PhotoURL)
                    .on('response', function(response) {
                        console.log(task.PhotoURL + ' : ' + response.statusCode, response.headers['content-type']);
                        console.log(task.target);
                    })
                    .on('error', function(err) {
                        console.log(err);
                    })
                    .pipe(fs.createWriteStream(task.target));
            }, 20);

            q.push(photo, function(err) {
                if (err) {
                    console.log(err);
                }
            });

            q.drain = function() {
                console.log('Done.')
            }

        });
    }
});

我做错了什么?非常感谢您的时间和帮助。

1 个答案:

答案 0 :(得分:1)

问题在于您为每张照片创建了一个新队列,每个队列只收到一张照片。相反,只创建一次队列(在forEach()之外)并将照片对象推送到它。您还缺少任务处理程序中的回调。例如:

var q = async.queue(function(task, cb) {
  request
    .get(task.PhotoURL)
    .on('response', function(response) {
      console.log(task.PhotoURL + ' : ' + response.statusCode, response.headers['content-type']);
      console.log(task.target);
      // the call to `cb` could instead be made on the file stream's `finish` event
      // if you want to wait until it all gets flushed to disk before consuming the
      // next task in the queue
      cb();
    })
    .on('error', function(err) {
      console.log(err);
      cb(err);
    })
    .pipe(fs.createWriteStream(task.target));
}, 20);

q.drain = function() {
  console.log('Done.')
};

photos.forEach(function(photo) {
  var url = photo.PhotoURL;
  var image = url.replace('http://someurl.com/media.ashx?id=', '').replace('&otherstuffattheend', '.jpg');
  photo.target = image;

  q.push(photo, function(err) {
    if (err) {
      console.log(err);
    }
  });
});