2015-06-15 1 views
0

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

function storeFileStream(file, next) { 
    createFileHash(file, function(err, hash) { 
     if (err) { 
      return next(err); 
     } 

     var fileName = path.join(config.storagePath, hash), 
      stream = fs.createWriteStream(fileName); 

     stream.on('error', function(err) { 
      return next(err); 
     }); 
     stream.on('finish', function() { 
      return next(); 
     }); 

     file.pipe(stream); 
    }); 
} 

function createFileHash(file, next) { 
    var hash = crypto.createHash('sha1'); 
    hash.setEncoding('hex'); 

    file.on('error', function(err) { 
     return next(err); 
    }); 
    file.on('end', function(data) { 
     hash.end(); 
     return next(null, hash.read()); 
    }); 

    file.pipe(hash); 
} 

Проблема заключается в том, что после того, как я известково файл хэша writed размер файла равен 0. Что такое лучший способ сделать решить эту задачу?

Обновление Согласно предложению @poke, я пытаюсь дублировать мой поток. Теперь мой код:

function storeFileStream(file, next) { 
    var s1 = new pass; 
    var s2 = new pass; 
    file.pipe(s1); 
    file.pipe(s2);   

    createFileHash(s1, function(err, hash) { 
     if (err) { 
      return next(err); 
     } 

     var fileName = path.join(config.storagePath, hash), 
      stream = fs.createWriteStream(fileName); 

     stream.on('error', function(err) { 
      return next(err); 
     }); 
     stream.on('finish', function() { 
      return next(); 
     }); 

     s2.pipe(stream); 
    }); 
} 

function createFileHash(file, next) { 
    var hash = crypto.createHash('sha1'); 
    hash.setEncoding('hex'); 

    file.on('error', function(err) { 
     return next(err); 
    }); 
    file.on('end', function(data) { 
     hash.end(); 
     return next(null, hash.read()); 
    }); 

    file.pipe(hash); 
} 

Проблема этого кода является то, что события end и finish не emited. Если я прокомментирую file.pipe(s2);, события будут выпущены, но я снова получаю мою проблему с исходным кодом.

+1

Так как вы трубы файл * поток * в хэш-функции, вы уже исчерпали поток полностью к тому времени, когда у вас есть хэш, и вы хотите записать файл. Вы можете сначала записать файл на диск, а затем прочитать его снова, чтобы вычислить хеш, или вам нужно дублировать поток вверх; см. [этот вопрос] (http://stackoverflow.com/questions/19553837/node-js-piping-the-same-stream-into-multiple-writable-targets). – poke

+0

@poke Благодарим за комментарий. Первый вариант не подходит для меня, потому что мне нужно сначала вывести хэш. Я пытаюсь дублировать поток с использованием потока PassThrough и использовать экземпляры PassThrough вместо параметра 'file'. Однако события «финиш» и «конец» теперь не выдаются. – Dmitriy

ответ

0

Этот код исправить проблему:

var s1 = new passThrough, 
    s2 = new passThrough; 

file.on('data', function(data) { 
    s1.write(data); 
    s2.write(data); 
}); 
file.on('end', function() { 
    s1.end(); 
    s2.end(); 
}); 
0

Вы можете использовать async модуль (не проверял, но должно работать):

async.waterfall([ 
    function(done) { 
     var hash = crypto.createHash('sha1'); 
     hash.setEncoding('hex'); 

     file.on('error', function(err) { 
      done(err); 
     }); 
     file.on('end', function(data) { 
      done(null, hash.read); 
     }); 

     file.pipe(hash); 

    }, 
    function(hash, done) { 
     var fileName = path.join(config.storagePath, hash), 
      stream = fs.createWriteStream(fileName); 

     stream.on('error', function(err) { 
      done(err); 
     }); 
     stream.on('finish', function() { 
      done(null); 
     }); 

     file.pipe(stream); 
    } 
], function (err) { 
    console.log("Everything is done!"); 
}); 
+0

Я пробую ваш код, и у него та же проблема: сохраненный файл пуст. На самом деле, я не знаю, почему это может мне помочь. Проблема чтения из уже поданного потока потока по-прежнему представлена ​​здесь, – Dmitriy

Смежные вопросы