我做了一些实验。看起来我们可以onprogress
通过利用result
reader 对象上的不完整来获取事件中读取的最后一个块。只有当我们使用reader.readAsArrayBuffer
(Chrome only?) 或reader.readAsBinaryString
. 字符串的问题在于,如果您想获取其中的一部分,则必须对其进行切片,从而生成副本(非常慢)。
ArrayBuffers 有一种.subarray
方法可以在缓冲区中创建视图,而无需复制任何数据。这正是我们想要的。但是,它似乎在基类上不可用;并且从文档中不清楚当我们Uint8Array
使用此缓冲区构造派生类(例如)时会发生什么,但考虑到原始缓冲区可通过只读属性访问,我假设它不是复制。
sjcl 和 CryptoJS 都有很方便的.update
方法来接收这个 ArrayBufferView,这样你就可以即时更新你的哈希值。因此,我提出了以下解决方案(使用 jQuery、下划线和 sjcl):
$(document).on('drop', function(dropEvent) {
dropEvent.preventDefault();
_.each(dropEvent.originalEvent.dataTransfer.files, function(file) {
var reader = new FileReader();
var pos = 0;
var hash = new sjcl.hash.sha256();
reader.onprogress = function(progress) {
var chunk = new Uint8Array(reader.result, pos, progress.loaded - pos);
pos = progress.loaded;
hash.update(chunk);
if(progress.lengthComputable) {
console.log((progress.loaded/progress.total*100).toFixed(1)+'%');
}
};
reader.onload = function() {
var chunk = new Uint8Array(reader.result, pos);
if(chunk.length > 0) hash.update(chunk);
console.log(sjcl.codec.hex.fromBits(hash.finalize()));
};
reader.readAsArrayBuffer(file);
});
});
请注意,此解决方案目前仅适用于 Chrome,而且速度相当慢。我认为 sjcl 不仅仅是对文件进行哈希处理,而是对其进行密钥强化,这真的不是我想要的。稍后将进行更多调查。