uniapp开发:微信小程序和JS的ArrayBuffer差异导致crypto-js库计算md5错误
业务需求和bug
业务需求
获取图片文件的md5值(图片通过uni.chooseImage上传),要兼容浏览器和微信小程序端。(本文使用浏览器环境为Chrome浏览器)
bug描述
浏览器端使用的 FileReader() 对象的 reader.readAsArrayBuffer(file) 方法转成 Arraybuffer,再使用 crypto-js 转成 md5。
微信小程序使用 FileSystemManager.readFile() API读取为 ArrayBuffer,再使用 crypto-js 转成 md5。
微信小程序无论什么图,获取到的md5都是 487f7b22f68312d2c1bbc93b1aea445b,浏览器端正常。
这部分代码大概如下:(从项目中摘取出来的,没真实运行,算是伪代码)
import CryptoJS from "crypto-js";
let arraybuffer = null
// 浏览器
// #ifdef WEB
const reader = new FileReader();
reader.onload = (e) => {
// 获取到的 ArrayBuffer
console.log(e.target.result)
arraybuffer = e.target.result
};
reader.onerror = (err) => {
console.log(err)
};
// 读取文件为 ArrayBuffer
reader.readAsArrayBuffer(file);
// #endif
// 微信小程序读取文件处理
// #ifdef MP-WEIXIN
const reader = uni.getFileSystemManager()
reader.readFile({
filePath: file.path, // 这里填入文件路径
encoding: "", // 留空,表示读取原始二进制数据
success: (res) => {
// 获取到的 ArrayBuffer
console.log(res.data)
arraybuffer = e.target.result
},
fail: (err) => {
console.error('读取文件失败', err);
}
});
// #endif
// CryptoJS 转 md5
const wordArray = CryptoJS.lib.WordArray.create(arraybuffer);
const md5 = CryptoJS.MD5(wordArray).toString();
排错过程
打印 arraybuffer 和 wordArray
分别在两端打印了获取到的 arraybuffer 和 wordArray,乍一看都问题,仔细对比才发现,两边的arraybuffer 不太一样??导致 CryptoJS.lib.WordArray.create 创建的 WordArray 也不对,不细看都没发现。这直接导致了后面 WordArray 转 md5 出现 bug。
(所有图:黑底微信是小程序、白底是浏览器)
wordArray 对比
目测两边一样


arraybuffer 对比
两边的 arraybuffer 看起来差不多,对象原型都是 ArrayBuffer。
( __proto__和 [[prototype]] 都是指原型对象,浏览器差异会有不同显示)


问题解决&结论
instanceof 查找原型链
instanceof用于判断一个对象是否是某个构造函数的实例,会沿着对象的原型链去查找是否有Constructor.prototype,如果有则返回true,否则返回false。
为什么原型对象都一样,但是生成出来的 wordArray 不一样 ????,试了很多,最后终于通过 instanceof 找到了答案:
代码:
console.log('instanceof ArrayBuffer', arraybuffer instanceof ArrayBuffer);
运行结果:
![]()
![]()
结论
微信小程序的原型对象 ArrayBuffer 非 JS 的原型对象 ArrayBuffer!!!!!!!!???
解决
手动将微信小程序原型对象设为JS 的原型对象,ArrayBuffer 尝试添加以下代码:
Object.setPrototypeOf(item.result, ArrayBuffer.prototype);
BUG解决,微信小程序 crypto-js 转 md5 结果正常。
PS:很痛苦的排错
更多推荐
所有评论(0)