Пользователи загружают файлы в мое экспресс-приложение. Мне нужно вычислить хэш загруженного файла, а затем записать файл на диск, используя вычисленный хеш в качестве имени файла. Я пытаюсь сделать это, используя следующий код:Рассчитать хэш файла и сохранить файл
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);
, события будут выпущены, но я снова получаю мою проблему с исходным кодом.
Так как вы трубы файл * поток * в хэш-функции, вы уже исчерпали поток полностью к тому времени, когда у вас есть хэш, и вы хотите записать файл. Вы можете сначала записать файл на диск, а затем прочитать его снова, чтобы вычислить хеш, или вам нужно дублировать поток вверх; см. [этот вопрос] (http://stackoverflow.com/questions/19553837/node-js-piping-the-same-stream-into-multiple-writable-targets). – poke
@poke Благодарим за комментарий. Первый вариант не подходит для меня, потому что мне нужно сначала вывести хэш. Я пытаюсь дублировать поток с использованием потока PassThrough и использовать экземпляры PassThrough вместо параметра 'file'. Однако события «финиш» и «конец» теперь не выдаются. – Dmitriy