fs.copy因大量图像而失败,适用于少量图像

时间:2015-07-28 19:22:12

标签: javascript node.js file asynchronous

我有一个文件名数组,我试图从一个目录复制到另一个目录。文件名在async series链中的函数中构建,然后在最终函数中,使用fs.copy复制它们。该脚本也在十个不同的目录上运行,所以我看起来像这样。它是简化的,但功能相同。

var dirs = [{
    'src': 'dir1',
    'dest': 'dest/dir1',
    'files': []
}, {
    'src': 'dir2',
    'dest': 'dest/dir2',
    'files': []
}, {
    'src': 'dir3',
    'dest': 'dest/dir3',
    'files': []
}, {
    'src': 'dir4',
    'dest': 'dest/dir4',
    'files': []
}];

async.series([function(callback){
 //get files
 dirs.forEach(function(currentSrc){
    fs.readdirSync(currentSrc);
 });
 callback();
},
function(callback){
  //make dest dirs with dirs.forEach and fs.mkdir
  callback();
},
function(callback){
  var src
    , dest;
  dirs.forEach(funtion(dir){
    dir.files.forEach(function(file){
      src = path.join(dir.src, file);
      dest = path.join(dir.dest, file);
      fs.copy(src, dest, {replace: false}, function(err) {
        if (err){
          console.log('error copying file: ', err);
        }
    });
  });
}]);

这适用于少量文件,但是当我尝试使用包含大约400MB的目录时,它失败了。所有文件似乎都在目的地,但是除了名称之外还有数据(这是正确的),但每个文件的文件大小为0.为什么这对少量文件起作用,但不是很大?

更新。我收到了错误

  

events.js:85         扔掉//未处理的'错误'事件

更新: 我现在正在使用@Jacob提供的策略,我现在拥有的是:

var dirs = [{
    'src': 'src/1',
    'dest': 'waterfallDest1',
    'files': []
}, {
    'src': 'src/2',
    'dest': 'waterfallDest2',
    'files': []
}, {
    'src': 'src/3',
    'dest': 'waterfallDest3',
    'files': []
}, {
    'src': 'src/4',
    'dest': 'waterfallDest4',
    'files': []
}];




async.eachLimit(dirs, 1000, function (dir, cb) {
    async.waterfall([
        function (cb) {
            fs.mkdir(dir.dest, cb);
        },
        function (cb) {
            fs.readdir(dir.src, cb);
        },
        function (files, cb) {
            async.eachLimit(files, 10, function (file, cb) {
                var src = path.join(dir.src, file);
                var dest = path.join(dir.dest, file);
                try { // In case fs.copy is indeed throwing an error
                    fs.copy(src, dest, {replace: false}, cb);
                } catch (err) {
                    cb('try-catch err ', err);
                }
            }, cb);
        }
    ], cb);
}, function (err) {
    if (err) {
        console.log('Some error happened:\n' + err.stack);
    }
});

这是成功创建所有目录,并成功将文件传输到第一个目录,但每个后续目录都填充了0k图像。

2 个答案:

答案 0 :(得分:0)

您需要对async.series电话进行最终回调:

async.series([
  function (callback) {
    dirs.forEach(function (currentSrc) {
      fs.readdirSync(currentSrc);
    });
    callback();
  },
  function (callback) {
    //make dest dirs with dirs.forEach and fs.mkdir
    callback();
  },
  function(callback) {
    var src, dest;
    dirs.forEach(funtion(dir){
      dir.files.forEach(function(file){
        src = path.join(dir.src, file);
        dest = path.join(dir.dest, file);
        fs.copy(src, dest, {replace: false}, function(err) {
          if (err){
            console.log('error copying file: ', err);
            // Did you want to do callback(err)?
          }
        });
      });
    })
    // Somewhere, this needs to call back.
  }
], function (err, result) {
  if (err) {
    // One of the steps had an error; handle it.
  }
});

以下是您的代码如何使用async.each来避免所有这些循环。它还包括一些限制,以避免操作系统一次打开太多文件:

async.eachLimit(dirs, 10, function (dir, cb) {
  async.waterfall([
    function (cb) {
      fs.mkdir(dir.dest, cb);
    },
    function (cb) {
      fs.readdir(dir.src, cb);
    },
    function (files, cb) {
      async.eachLimit(files, 10, function (file, cb) {
        var src = path.join(dir.src, file);
        var dest = path.join(dir.dest, file);
        try { // In case fs.copy is indeed throwing an error
          fs.copy(src, dest, {replace: false}, cb);
        } catch (err) {
          cb(err);
        }
      }, cb);
    }
  ], cb);
}, function (err) {
  if (err) {
    console.log('Some error happened:\n' + err.stack);
  }
});

答案 1 :(得分:0)

Per the documentation“您可以使用try / catch来处理异常或允许它们冒泡。”

function load() {
};

对于它的价值,底层库ncp应归咎于fs内的零星回调。 fs issues IF ncp幕后花絮多次为单个文件调用回调,然后第二次回调会抛出一个异常......文件已经存在。