2015-10-08 7 views
0

Я разрабатываю функцию множественной загрузки файлов с помощью ajax, nodejs, express и модуля.Не удается отправить заголовки после их отправки. Загрузка файла, проблема с асинхронностью?

Однако я иногда получаю ошибку Can't set headers after they are sent. из трассировки стека ошибок, это из-за линии return res.send({ status: 'success', files: files['upload']

Я попытался проанализировать, что может сделать ее переслали несколько раз, и я включил счетчик, чтобы сделать уверенный, что он будет запущен один раз, как только все файлы будут загружены, но ошибка все равно иногда происходит.

var express  = require('express'), 
    router  = express.Router(), 
    formidable = require('formidable'), 
    util  = require('util'), 
    fs   = require('fs'), 
    form  = new formidable.IncomingForm(), 
    path  = require('path'), 
    nodeHomeDir = path.dirname(require.main.filename); 

form.type = 'multipart'; 
form.multiples = true; 
form.maxFieldsSize = 52428800; 
form.uploadDir = nodeHomeDir + '/tmp'; 
form.keepExtensions = true; 

/* POST to /files to upload or delete files */ 
router.post('/', function (req, res, next) { 

    form.parse(req, function (err, fields, files) { 
    if (!files['upload'][0]) return res.send({ status: 'fail', message: 'No files provided.' }); 

    req.on('aborted', function() { 
     return res.send({ message: 'fail' }); 
    }); 

    var webinarID  = fields.webinarID, 
     uploadDirName = nodeHomeDir + '/webinarFiles/' + webinarID, 
     filesLength = Object.keys(files['upload']).length, 
     counter  = 0; 

    if (!webinarID) return res.send({ status: 'fail', message: 'No webinar ID provided.' }); 

    if (!fs.existsSync(uploadDirName)) { 
     fs.mkdirSync(uploadDirName); 
    } 

    for (file in files['upload']) { 
     if (files['upload'][file] && files['upload'][file].path && files['upload'][file].name) { 
     var stream = fs.createReadStream(files['upload'][file].path).pipe(fs.createWriteStream(uploadDirName + '/' + files['upload'][file].name)); 
     stream.on('finish', function() { 
      counter++; 
      if (counter === filesLength) { 
      // deleteFilesFromFolder(nodeHomeDir + '/tmp'); 
      return res.send({ status: 'success', files: files['upload'] }); 
      } 
     }); 
     } 
    } 

    }); 

}); 
+0

Ну, массив ключей вы получите назад от 'Object.keys()' не обязательно такой же длины, как количество свойств а 'для .. . в циклах будет проходить итерация. Если вы хотите быть уверенным, что выполняете итерацию только через одни и те же ключи, то итерации через результат объекта Object.keys() непосредственно с помощью простого цикла 'for' или с помощью' .forEach() '. – Pointy

ответ

0

Попробуйте это:

var async = require('async'); 
    async.eachSeries(files['upload'], function(elem,asynccallback){ 
    if (files['upload'][file] && files['upload'][file].path && files['upload'][file].name) { 
      var stream = fs.createReadStream(files['upload'][file].path).pipe(fs.createWriteStream(uploadDirName + '/' + files['upload'][file].name)); 
      stream.on('finish', function() { 
       counter++; 
       if (counter === filesLength) { 
       // deleteFilesFromFolder(nodeHomeDir + '/tmp'); 
       return res.send({ status: 'success', files: files['upload'] }); 
       } 
      }); 
      } 
    asynccallback(); 
});