FileReader (). ReadAsArrayBuffer (файл) результат застревает после первого загруженного файла - PullRequest
2 голосов
/ 10 июня 2019

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

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

CodeSandBox: https://codesandbox.io/s/file-reader-md5so-nem6v

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

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

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

enter image description here

РЕДАКТИРОВАТЬ: Оказывается, вам нужно создать типизированный массив из ArrayBuffer для работы с результатами readAsArrayBuffer()

От: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer

Объект ArrayBuffer используется для представления общего буфера исходных двоичных данных фиксированной длины.

Это массив байтов, который в других языках часто называют "байтовым массивом".

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

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.log("onFileSelect...");
    generateHashAndSave(event.target.files[0], index);
  }

  function generateHashAndSave(file, index) {
    console.log("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);

1 Ответ

1 голос
/ 10 июня 2019

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

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

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

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

...