使用FileReader()读取文件以从图像文件生成md5哈希字符串的正确方法?

时间:2019-06-07 16:30:21

标签: javascript hash md5 filereader

我目前正在执行此操作(请参见下面的代码段),以获取要上传的图像文件的md5哈希字符串(我将哈希用作fileNames):

注意::我正在使用md5包来生成哈希(哈希已加载到摘要中)。

FileReader()上有4种可用的方法来读取文件。它们似乎都能产生良好的结果。

  • readAsText(文件)
  • readAsBinaryString(file);
  • readAsArrayBuffer(file);
  • readAsDataURL(file);

在这种情况下,我应该使用哪个?为什么?您还能解释它们之间的区别吗?

function onFileSelect(e) {
  const file = e.target.files[0];
  const reader1 = new FileReader();
  const reader2 = new FileReader();
  const reader3 = new FileReader();
  const reader4 = new FileReader();
  
  reader1.onload = (event) => {
    const fileContent = event.target.result;
    console.log('Hash from "readAsText()": ');
    console.log(md5(fileContent));
  }
  
  reader2.onload = (event) => {
    const fileContent = event.target.result;
    console.log('Hash from "readAsBinaryString()": ');
    console.log(md5(fileContent));
  }
  
  reader3.onload = (event) => {
    const fileContent = event.target.result;
    console.log('Hash from "readAsArrayBuffer()": ');
    console.log(md5(fileContent));
  }
  
  reader4.onload = (event) => {
    const fileContent = event.target.result;
    console.log('Hash from "readAsDataURL()": ');
    console.log(md5(fileContent));
  }
  
  reader1.readAsText(file);
  reader2.readAsBinaryString(file);
  reader3.readAsArrayBuffer(file);
  reader4.readAsDataURL(file);
  
}
.myDiv {
  margin-bottom: 10px;
}
<script src="https://cdn.jsdelivr.net/npm/js-md5@0.7.3/src/md5.min.js"></script>
<div class="myDiv">Pick an image file to see the 4 hash results on console.log()</div>
<input type='file' onChange="onFileSelect(event)" accept='.jpg,.jpeg,.png,.gif' />

1 个答案:

答案 0 :(得分:1)

使用readAsArrayBuffer

readAsBinaryString()readAsDataURL()将使您的计算机完成比需要完成的工作更多的工作:

  1. 将blob读取为二进制流
  2. 转换为UTF-16 / base64字符串(记住在js中字符串不是可变的,您对其执行的任何操作实际上都会在内存中创建一个副本)
  3. [传递给您的lib]
  4. 转换为二进制字符串
  5. 处理数据

另外,看来您的库无法处理数据URL,并且无法处理UTF-16字符串。

readAsText()默认情况下会尝试将二进制数据解释为UTF-8文本序列,这对于像光栅图像这样的二进制数据非常不利:

// generate some binary data
document.createElement('canvas').toBlob(blob => {
  const utf8_reader = new FileReader();
  const bin_reader = new FileReader();
  let done = 0;
  utf8_reader.onload = bin_reader.onload = e => {
    if(++done===2) {
      console.log('same results: ', bin_reader.result === utf8_reader.result);
      console.log("utf8\n", utf8_reader.result);
      console.log("utf16\n", bin_reader.result);
    }
  }
  utf8_reader.readAsText(blob);
  bin_reader.readAsBinaryString(blob);
});

另一方面,

readAsArrayBuffer只会像分配内存中那样分配二进制数据。简单的I / O,无需处理。
为了处理这些数据,我们可以在该二进制数据上使用TypedArrays视图,这些视图仅仅是视图,也不会产生任何开销。

如果您查看the library you are using,他们将把您的输入传递给这样的Uint8Array进行进一步处理。但是请注意,它们显然需要您传递此ArrayBuffer的Uint8Array视图,而不是直接传递裸ArrayBuffer。