Правильный способ чтения файла с помощью FileReader() для создания строки хеша md5 из файлов изображений?

В настоящее время я делаю это (см. Фрагмент ниже), чтобы получить md5 хэш-строка для файлов изображений, которые я загружаю (я использую хэш как fileNames):

ПРИМЕЧАНИЕ: я использую md5 пакет для генерации хеша (он загружается во фрагмент).

Есть 4 доступных метода на FileReader() читать файлы. Все они, кажется, дают хорошие результаты.

  • readAsText(файл)
  • readAsBinaryString (файл);
  • readAsArrayBuffer (файл);
  • readAsDataURL (файл);

Что я должен использовать в этом случае и почему? Можете ли вы также объяснить разницу между ними?

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 ответ

Решение

использование readAsArrayBuffer,

readAsBinaryString() а также readAsDataURL() заставит ваш компьютер выполнять намного больше работы, чем нужно сделать:

  1. читать BLOB-объекты как двоичный поток
  2. преобразовать в строку UTF-16 / base64 (помните, что строки не являются изменяемыми в js, любая операция, которую вы выполняете над этим, фактически создает копию в памяти)
  3. [перейти к вашей библиотеке]
  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 с другой стороны, будет просто распределять двоичные данные как есть в памяти. Простой ввод / вывод, без обработки.
Чтобы манипулировать этими данными, мы можем использовать представления TypedArrays для этих двоичных данных, которые, будучи только представлениями, также не будут создавать никаких накладных расходов.

И если вы посмотрите на библиотеку, которую вы используете, они в любом случае передадут ваш ввод в такой массив Uint8Array для дальнейшей обработки. Однако имейте в виду, что они, очевидно, нуждаются в том, чтобы вы передавали представление ArintBuffer в Uint8Array вместо обнаженного ArrayBuffer.

Другие вопросы по тегам