1

我在上传之前使用crypto-js来计算我的文件的MD5 校验和,下面是我的代码。

import CryptoJS from "crypto-js";

const getMd5 = async (fileObject) => {
  let md5 = "";
  try {
    const fileObjectUrl = URL.createObjectURL(fileObject);
    const blobText = await fetch(fileObjectUrl)
      .then((res) => res.blob())
      .then((res) => new Response(res).text());

    const hash = CryptoJS.MD5(CryptoJS.enc.Latin1.parse(blobText));
    md5 = hash.toString(CryptoJS.enc.Hex);
  } catch (err) {
    console.log("Error occured getMd5:", err);
  }
  return md5;
};

以上代码仅适用于文本文件,但在处理非文本文件图像、视频等时,校验和计算不正确。

任何帮助/输入表示赞赏。谢谢!

4

2 回答 2

2

只需将结果直接.then((res) => res.blob())输入MD5函数即可。

编码到text()可能是有损的(和/或使用替换字符),并且Latin1也不涵盖所有可能的字节值 - 至少正式。也无需转换为文本然后再转换为二进制。

它需要转换为 CryptoJS 可以接受的二进制表示 - 如另一个答案中所实现的那样。然而,这需要是二进制到二进制的转换,而不是二进制 -> 文本 -> 二进制转换。

于 2021-07-08T13:13:58.857 回答
2

Response.text()读取响应流并使用 UTF-8 编码将其转换为字符串。不符合 UTF-8 的任意二进制数据将在此过程中被破坏(例如图像、视频等),s。还有另一个答案。
这可以通过使用Response.arrayBuffer()来防止,它只是将数据原封不动地存储在ArrayBuffer.
由于 CryptoJS 在内部与WordArrays 一起工作,因此需要进一步将 the 转换ArrayBuffer为 a WordArray

以下修复适用于我的机器:

(async () => {
            
    const getMd5 = async(fileObject) => {
        let md5 = "";
        try {
            const fileObjectUrl = URL.createObjectURL(blob);
            const blobText = await fetch(fileObjectUrl)
                .then((res) => res.blob())
                .then((res) => new Response(res).arrayBuffer());                    // Convert to ArrayBuffer       
            const hash = CryptoJS.MD5(CryptoJS.lib.WordArray.create(blobText)); // Import as WordArray
            md5 = hash.toString(CryptoJS.enc.Hex);
        } catch (err) {
            console.log("Error occured getMd5:", err);
        }
        return md5;
    };
        
    const blob = new Blob([new Uint8Array([0x01, 0x02, 0x03, 0x7f, 0x80, 0x81, 0xfd, 0xfe, 0xff])]);
    console.log(await(getMd5(blob)));
        
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>

为简单起见,我没有使用文件对象进行测试,而是使用不兼容 UTF8 的数据的 blob 对象。生成的哈希是正确的,可以在线验证,例如这里

于 2021-07-08T14:53:18.437 回答