2015-06-15 25 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); 
} 

的問題是,在我calc下文件哈希所著的文件大小爲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); 
} 

這段代碼的問題是,事件endfinish不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