Результат FileReader().readAsArrayBuffer(file) застревает после загрузки первого файла

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

Почему-то результат метода readAsArrayBuffer(file) API FileReader() зависает после того, как я прочитал первый файл.

КодПесочница:https://codesandbox.io/s/file-reader-md5so-nem6v

Если я изменю метод чтения на readAsText(file), результаты будут нормальными, и я получу другой хэш для другого файла. Но мне сказали, что readAsArrayBuffer() больше подходит для файлов изображений. Вот почему я его использую.

Что может происходить? Нужно ли очищать какой-то буфер?

GIF странного поведения:

Результат FileReader().readAsArrayBuffer(file) застревает после загрузки первого файла

Обновлено: Оказывается нужно создать типизированный массив из 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);
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
1 017
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен на 100%, что происходит, но это выглядит похоже на проблему с библиотекой md5(), которую вы используете. Если вы явно превратите экземпляр ArrayBuffer в Uint8Array, то ничего странного не произойдет:

  aux[index].md5Hash = md5(new Uint8Array(event.target.result));

дает разные значения хеш-функции для разных изображений.

Возможно, ваш md5() на самом деле не ожидает ArrayBuffer аргументов, так что в этом случае, я полагаю, это не совсем «ошибка».

Спасибо! В документах md5 говорится, что ожидается String or Buffer. Как вы думаете, это проблема?

cbdeveloper 10.06.2019 19:36

@ cbdev420 ну, я не уверен; все, что я знаю, это то, что он отлично работает, когда вы даете ему типизированный массив. Это дало мне точно такое же не совсем хэш-значение, которое вы показываете в том, что вы разместили здесь, так что это заставляет меня думать, что это хэширует какой-то конкретный повторяемый набор байтов из экземпляра ArrayBuffer; Я не знаю, как и почему.

Pointy 10.06.2019 19:38

@cbdev420 хорошо может быть; проблема с нетекстовыми данными, такими как данные изображения, заключается в том, что могут быть нераспознаваемые последовательности UTF-16, и это может вызвать проблемы. Я не уверен. Создание нового массива не должно быть таким дорогим; ему не нужно выделять память, потому что буфер уже есть.

Pointy 10.06.2019 19:52

Я полагаю, вы правы. Документы MDN о ArrayBuffer говорят: Вы не можете напрямую манипулировать содержимым ArrayBuffer; вместо этого вы создаете один из объектов типизированного массива или объект DataView, который представляет буфер в определенном формате, и используете его для чтения и записи содержимого буфера.

cbdeveloper 10.06.2019 20:11

Лучший массив типов для меня — это Uint8array? Или это не имеет большого значения? Int8, Int16, Int32?

cbdeveloper 10.06.2019 20:12

Ну Uint8Array, кажется, работает, так что это сильный соперник :) Я сомневаюсь, что это имеет значение, пока данный тип работает (например, это имеет значение, если вы, конечно, получаете какое-то исключение во время выполнения)

Pointy 10.06.2019 20:13

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