txt 以外的文件的 MD5 校验和计算不正确?
MD5 checksum not calculated properly for files other than txt?
我正在使用 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;
};
以上代码仅适用于文本文件,但适用于非文本文件文件图像、视频等,校验和计算错误
任何 help/input 表示赞赏。
谢谢!
只需将 .then((res) => res.blob())
的结果直接输入 MD5
函数即可。
编码为 text()
可能是有损的(and/or 使用替换字符),并且 Latin1
也没有涵盖所有可能的字节值范围 - 至少官方是这样。只是不需要先转换为文本再转换回二进制。
需要转换为 CryptoJS 可以接受的二进制表示形式 - 已实现 。然而,这需要是二进制到二进制的转换,而不是二进制 -> 文本 -> 二进制转换。
Response.text()
读取响应流并使用 UTF-8 编码将其转换为字符串。不符合 UTF-8 标准的任意二进制数据将在此过程中损坏(例如图像、视频等),s。还有另一个答案。
这是通过使用 Response.arrayBuffer()
来防止的,它只是将数据不变地存储在 ArrayBuffer
.
中
由于 CryptoJS 在内部使用 WordArray
s,因此需要将 ArrayBuffer
进一步转换为 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 对象。
生成的哈希是正确的,可以在线验证,例如here
我正在使用 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;
};
以上代码仅适用于文本文件,但适用于非文本文件文件图像、视频等,校验和计算错误
任何 help/input 表示赞赏。 谢谢!
只需将 .then((res) => res.blob())
的结果直接输入 MD5
函数即可。
编码为 text()
可能是有损的(and/or 使用替换字符),并且 Latin1
也没有涵盖所有可能的字节值范围 - 至少官方是这样。只是不需要先转换为文本再转换回二进制。
需要转换为 CryptoJS 可以接受的二进制表示形式 - 已实现
Response.text()
读取响应流并使用 UTF-8 编码将其转换为字符串。不符合 UTF-8 标准的任意二进制数据将在此过程中损坏(例如图像、视频等),s。还有另一个答案。
这是通过使用 Response.arrayBuffer()
来防止的,它只是将数据不变地存储在 ArrayBuffer
.
中
由于 CryptoJS 在内部使用 WordArray
s,因此需要将 ArrayBuffer
进一步转换为 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 对象。 生成的哈希是正确的,可以在线验证,例如here