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