Я использую этот код для создания хеш-строки md5
, которая будет использоваться в качестве имен файлов в моем хранилище. Я читаю содержимое файла (изображения) и вычисляю хэш с помощью библиотеки md5
.
Почему-то результат метода readAsArrayBuffer(file)
API FileReader()
зависает после того, как я прочитал первый файл.
КодПесочница:https://codesandbox.io/s/file-reader-md5so-nem6v
Если я изменю метод чтения на readAsText(file)
, результаты будут нормальными, и я получу другой хэш для другого файла. Но мне сказали, что readAsArrayBuffer()
больше подходит для файлов изображений. Вот почему я его использую.
Что может происходить? Нужно ли очищать какой-то буфер?
GIF странного поведения:
Обновлено: Оказывается нужно создать типизированный массив из ArrayBuffer
для работы с результатами из readAsArrayBuffer()
От кого: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer
The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer.
It is an array of bytes, often refered to in other languages as a "byte array".
You cannot directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects or a DataView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import md5 from "md5";
import "./styles.css";
function App() {
const [images, setImages] = useState([{ md5Hash: null }, { md5Hash: null }]);
function onFileSelect(event, index) {
console.info("onFileSelect...");
generateHashAndSave(event.target.files[0], index);
}
function generateHashAndSave(file, index) {
console.info("Generate Hash...");
const reader = new FileReader();
reader.onload = event => {
setImages(prevState => {
const aux = Array.from(prevState);
aux[index].md5Hash = md5(event.target.result);
return aux;
});
};
reader.readAsArrayBuffer(file);
}
const inputItems = images.map((item, index) => (
<input
key = {index}
type = "file"
onChange = {event => onFileSelect(event, index)}
accept = ".jpg,.jpeg,.png,.gif"
/>
));
return (
<React.Fragment>
{inputItems}
<div><b>File 1 md5Hash: </b>{images[0].md5Hash}</div>
<div><b>File 2 md5Hash: </b>{images[1].md5Hash}</div>
</React.Fragment>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Я не уверен на 100%, что происходит, но это выглядит похоже на проблему с библиотекой md5()
, которую вы используете. Если вы явно превратите экземпляр ArrayBuffer
в Uint8Array
, то ничего странного не произойдет:
aux[index].md5Hash = md5(new Uint8Array(event.target.result));
дает разные значения хеш-функции для разных изображений.
Возможно, ваш md5()
на самом деле не ожидает ArrayBuffer
аргументов, так что в этом случае, я полагаю, это не совсем «ошибка».
@ cbdev420 ну, я не уверен; все, что я знаю, это то, что он отлично работает, когда вы даете ему типизированный массив. Это дало мне точно такое же не совсем хэш-значение, которое вы показываете в том, что вы разместили здесь, так что это заставляет меня думать, что это хэширует какой-то конкретный повторяемый набор байтов из экземпляра ArrayBuffer
; Я не знаю, как и почему.
@cbdev420 хорошо может быть; проблема с нетекстовыми данными, такими как данные изображения, заключается в том, что могут быть нераспознаваемые последовательности UTF-16, и это может вызвать проблемы. Я не уверен. Создание нового массива не должно быть таким дорогим; ему не нужно выделять память, потому что буфер уже есть.
Я полагаю, вы правы. Документы MDN о ArrayBuffer
говорят: Вы не можете напрямую манипулировать содержимым ArrayBuffer; вместо этого вы создаете один из объектов типизированного массива или объект DataView, который представляет буфер в определенном формате, и используете его для чтения и записи содержимого буфера.
Лучший массив типов для меня — это Uint8array
? Или это не имеет большого значения? Int8
, Int16
, Int32
?
Ну Uint8Array
, кажется, работает, так что это сильный соперник :) Я сомневаюсь, что это имеет значение, пока данный тип работает (например, это имеет значение, если вы, конечно, получаете какое-то исключение во время выполнения)
Спасибо! В документах
md5
говорится, что ожидаетсяString or Buffer
. Как вы думаете, это проблема?