编辑:从" JS File API更改标题 - 写入和读取UTF-8数据不一致" 以反映实际问题。
我有一些二进制内容我需要计算MD5。内容是WARC文件,这意味着它包含文本和编码图像。为了避免文件保存中的错误,我将所有数据转换并存储在arrayBuffers中。所有数据都放在UInt8Array
中以将其转换为UTF-8。
我的首次尝试是使用saveAs
库来保存Chrome扩展程序中的文件。这意味着我正在使用blob对象传递给该方法并创建该文件。
var b = new Blob(arrayBuffers, {type: "text/plain;charset=utf-8"});
saveAs(b,'name.warc');
我还没有找到一个从Blob
对象计算MD5的工具,所以我正在做的是使用FileReader
将blob文件作为二进制数据读取,然后使用MD5工具(我使用cryptoJS以及来自faultylabs的工具)来计算结果。
f = new FileReader();
f.readAsBinaryString(b);
f.onloadend = function(a){
console.log( 'Original file checksum: ', faultylabs.MD5(this.result) );
}
资源(图片)直接以arraybuffer
格式下载,因此我无需转换它们。
结果是错误的,这意味着从代码中检查MD5并从我保存在本地计算机上的文件中检查它会产生2种不同的结果。阅读文本,显然会发出错误。
我发现的解决方法包括使用文件系统API在磁盘上编写blob对象,然后将其作为二进制数据读回,计算MD5,然后将检索到的文件保存为WARC文件(不是直接将blob对象保存,而是"刷新"文件版本)。 在这种情况下,计算出的MD5很好(我在"刷新"版本的warc文件中计算它)但是当我使用"刷新"启动WARC重播实例时warc存档,它会让我错误 - 虽然原始文件我没有任何问题(但MD5不正确)。
var fd = new FormData();
// To compute the md5 hash and to have it correct on the server side, we need to write the file to the system, read it back and then calculate the md5 value.
// We need to send this version of the warc file to the server as well.
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
function computeWARC_MD5(callback,formData) {
window.requestFileSystem(window.TEMPORARY, b.size, onInitFs);
function onInitFs(fs) {
fs.root.getFile('warc.warc', {create: true}, function(fileEntry) {
fileEntry.createWriter(function(fileWriter) {
fileWriter.onwriteend = function(e) {
readAndMD5();
};
fileWriter.onerror = function(e) {
console.error('Write failed: ' + e.toString());
};
fileWriter.write(b);
});
});
function readAndMD5() {
fs.root.getFile('warc.warc', {}, function(fileEntry) {
fileEntry.file( function(file) {
var reader = new FileReader();
reader.onloadend = function(e) {
var warcMD5 = faultylabs.MD5( this.result );
console.log(warcMD5);
var g = new Blob([this.result],{type: "text/plain;charset=utf-8"});
saveAs(g, o_request.file);
formData.append('warc_file', g)
formData.append('warc_checksum_md5', warcMD5.toLowerCase());
callback(formData);
};
reader.readAsBinaryString(file);
});
});
}
}
}
function uploadData(formData) {
// upload
$.ajax({
type: 'POST',
url: server_URL_upload,
data: fd,
processData: false,
contentType: false,
// [SPECS] fire a progress event named progress at the XMLHttpRequestUpload object about every 50ms or for every byte transmitted, whichever is least frequent
xhrFields: {
onprogress: function (e) {
if (e.lengthComputable) {
console.log(e.loaded / e.total * 100 + '%');
}
}
}
}).done(function(data) {
console.log('done uploading!');
//displayMessage(port_to_page, 'Upload finished!', 'normal')
//port_to_page.postMessage( { method:"doneUpload" } );
});
}
computeWARC_MD5(uploadData, fd);
saveAs(b, 'warc.warc');
有人可以解释为什么会出现这种差异吗?在将我处理的所有对象视为二进制数据(存储,读取)时,我缺少什么?
答案 0 :(得分:1)
基本上我尝试了另一条路径并将blob文件转换回arraybuffer并计算了MD5。此时,文件的MD5和数组缓冲区是相同的。
var b = new Blob(arrayBuffers, {type: "text/plain;charset=utf-8"});
var blobHtml = new Blob( [str2ab(o_request.main_page_html)], {type: "text/plain;charset=utf-8"} );
f = new FileReader();
f.readAsArrayBuffer(b);
f.onloadend = function(a){
var warcMD5 = faultylabs.MD5(this.result);
var fd = new FormData();
fd.append('warc_file', b)
fd.append('warc_checksum_md5', warcMD5.toLowerCase());
uploadData(fd);
}
我猜二进制字符串和缓冲区数组的结果不同,这就是MD5不一致的原因。