私はいくつかの実験をしました。リーダー オブジェクトonprogress
の incomplete を利用することで、イベント内で読み取られた最後のチャンクを取得できるようです。result
( Chromereader.readAsArrayBuffer
のみ?) または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 はファイルをハッシュするだけではなく、キーを強化していると思いますが、これは本当に私が望んでいるものではありません。後で詳しく調べます。