如何使用文件阅读器从 Angular 中的文件生成 SHA1?

How to make a SHA1 from a file in Angular using a filereader?

我的 html 页面上有一个输入元素,我可以用它 select 1/多个文件。
选择文件后,我想使用 FileReader 读取每个文件的内容,从中生成 SHA1。
一旦我有了 SHA1 值,我想把它保存在某个地方。

问题是我仅在 FileReader 的 .onload 完成后才收到 SHA1 值,并且在我尝试保护它的值后发生这种情况。

我曾尝试使函数异步并使用 await 等待文件被读取,但这没有用。 我尝试添加一个 Promise,但这也没有用。
我真的不知道该怎么做才能得到想要的结果。请帮忙。

这是我选择文件后调用的 angular 函数:

hashFiles(files: Array<any>){
    console.log('start hashing');
    for (const file of files) {
      const myHash = hashFile(file);
      console.log('hash: ', myHash);
      /*I would like to save myHash here*/
    }
    console.log('done hashing');
}

这是从 angular 调用的我的 javascript 函数,它将使用 FileReader 读取文件,然后根据其内容生成 sha1 哈希值

function hashFile(fileToHandle) {
  console.log('1');

  var reader = new FileReader();

  console.log('2');

  reader.onload = (function() {

    return function(e) {
      console.log('4');

      const hash = CryptoJS.SHA1(arrayBufferToWordArray(e.target.result)).toString();
      console.log('hash result in fileReader: ', hash);
      return hash;
    };
  }) (fileToHandle);
  reader.onerror = function(e) {
    console.error(e);
  };

  console.log('3');

  reader.readAsArrayBuffer(fileToHandle);

  console.log('5');
}

function arrayBufferToWordArray(ab) {
  var i8a = new Uint8Array(ab);
  var a = [];
  for (var i = 0; i < i8a.length; i += 4) {
    a.push(i8a[i] << 24 | i8a[i + 1] << 16 | i8a[i + 2] << 8 | i8a[i + 3]);
  }
  return CryptoJS.lib.WordArray.create(a, i8a.length);
}

当运行此代码时,我的控制台中有以下内容:

start hashing
1
2
3
5
hash: undefined
done hashing
4
hash result in fileReader: 327c468b64b4ca54377546f8a214d703ccbad64b

我需要它是:

start hashing
1
2
3
hash result in fileReader: 327c468b64b4ca54377546f8a214d703ccbad64b
4
5
hash: 327c468b64b4ca54377546f8a214d703ccbad64b
done hashing

这是我的代码示例:
https://stackblitz.com/edit/sha1-from-file

您需要使用回调或向 FileReader 的本机回调添加一个 promise 包装器(observable 也可以)。以下是您可以通过添加回调来实现的方法。

Stackblitz

app.component.ts

hashFiles(event) {
  console.log('start hashing');

  const numberOfFiles = event.target.files.length;
  var fileCounter = 0;
  for (const file of event.target.files) {
    hashFile(file, (hashedFile, hash) => {
    console.log('hash: ', hash);
    fileCounter++;
    if(fileCounter === numberOfFiles)
      console.log('Done Hashing!');
    });
  }
}

script.js

export function hashFile(fileToHandle, callback) {
  var CryptoJS = require("crypto-js");

  console.log('1');

  var reader = new FileReader();

  console.log('2');

  reader.onloadend = (function() {
    return function(e) {
      console.log('4');
      const hash = CryptoJS.SHA1(arrayBufferToWordArray(e.target.result)).toString();
      console.log('hash result in fileReader: ', hash);
      callback(fileToHandle, hash);
    };
  }) (fileToHandle);
  reader.onerror = function(e) {
    console.error(e);
  };

  console.log('3');

  reader.readAsArrayBuffer(fileToHandle);
}