使用crypto模块的流功能获取文件的哈希值(即:没有hash.update和hash.digest)

Car*_*rós 37 hash stream node.js

cryptonode.js 的模块(至少在撰写本文时)仍然被认为是稳定的,因此API可能会发生变化.实际上,互联网上的每个人用来获取文件的哈希值(md5,sha1,...)的方法都被认为是遗留的(来自Hash的文档)(注意:强调我的):

类:哈希

用于创建数据的哈希摘要的类.

它是一个可读写的流.写入的数据用于计算哈希值.一旦流的可写端结束,使用read()方法获取计算的哈希摘要.在 传统的更新和消化方法也支持.

由crypto.createHash返回.

尽管hash.update并且hash.digest被认为是遗留的,但引用的片段上方显示的示例正在使用它们.

在不使用这些遗留方法的情况下获得哈希的正确方法是什么?

Car*_*rós 78

来自问题中引用的片段:

[哈希类]它是一个可读写的流.写入的数据用于计算哈希值.一旦流的可写端结束,使用read()方法获取计算的哈希摘要.

那么你需要散列一些文字是:

var crypto = require('crypto');

// change to 'md5' if you want an MD5 hash
var hash = crypto.createHash('sha1');

// change to 'binary' if you want a binary hash.
hash.setEncoding('hex');

// the text that you want to hash
hash.write('hello world');

// very important! You cannot read from the stream until you have called end()
hash.end();

// and now you get the resulting hash
var sha1sum = hash.read();
Run Code Online (Sandbox Code Playgroud)

如果要获取文件的哈希值,最好的方法是从文件创建一个ReadStream并将其传递到哈希:

var fs = require('fs');
var crypto = require('crypto');

// the file you want to get the hash    
var fd = fs.createReadStream('/some/file/name.txt');
var hash = crypto.createHash('sha1');
hash.setEncoding('hex');

fd.on('end', function() {
    hash.end();
    console.log(hash.read()); // the desired sha1sum
});

// read all file and pipe it (write it) to the hash object
fd.pipe(hash);
Run Code Online (Sandbox Code Playgroud)

  • 而不是`fd.on('end')`,最好处理`hash.on('finish')`,它不需要调用`hash.end()`. (5认同)
  • 在我看来,管道到哈希对象的方法比老式的 `stream.on('data', data => hash.update(data))` 和后来调用 `digest('hex' )`。当我进行了如上所述的精确实验但省略了“hash.read()”时,因为我想在写入流的“finish”事件上执行此操作,但我什么也没得到,没有任何价值。只有当我在上面的“end”事件处理程序中调用“hash.read()”(或在@HermanKan建议的“finish”中)时,我才能得到哈希值。在“data”事件处理程序中调用“hash.update(...)”没有这样的问题,然后我可以随时随地获取哈希输出。 (2认同)

DS.*_*DS. 19

返回哈希摘要的Promise的ES6版本:

function checksumFile(hashName, path) {
  return new Promise((resolve, reject) => {
    const hash = crypto.createHash(hashName);
    const stream = fs.createReadStream(path);
    stream.on('error', err => reject(err));
    stream.on('data', chunk => hash.update(chunk));
    stream.on('end', () => resolve(hash.digest('hex')));
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个。此处可能的改进:https://gist.github.com/F1LT3R/2e4347a6609c3d0105afce68cd101561 (2认同)

Afa*_*kin 14

卡洛斯回答的简短版本:

var fs = require('fs')
var crypto = require('crypto')

fs.createReadStream('/some/file/name.txt').
  pipe(crypto.createHash('sha1').setEncoding('hex')).
  on('finish', function () {
    console.log(this.read()) //the hash
  })
Run Code Online (Sandbox Code Playgroud)


Har*_*ell 12

进一步完善,ECMAScript 2015

function checksumFile(algorithm, path) {
  return new Promise((resolve, reject) =>
    fs.createReadStream(path)
      .on('error', reject)
      .pipe(crypto.createHash(algorithm)
        .setEncoding('hex'))
      .once('finish', function () {
        resolve(this.read())
      })
  )
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我成功地使用了 Node 模块 hasha,代码变得非常干净和简短。它返回一个 promise,因此您可以将它与 await 一起使用:

const hasha = require('hasha');

const fileHash = await hasha.fromFile(yourFilePath, {algorithm: 'md5'});
Run Code Online (Sandbox Code Playgroud)