FileReader()。readAsArrayBuffer(file)结果在第一次加载文件后卡住

时间:2019-06-10 17:18:08

标签: javascript reactjs browser filereader arraybuffer

我正在使用此代码生成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 个答案:

答案 0 :(得分:1)

我不是100%知道发生了什么,但是看起来就像您正在使用的md5()库存在问题。如果您将ArrayBuffer实例显式转换为Uint8Array,那么事情就不会变得很奇怪:

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

为不同的图像提供不同的哈希值。

您的md5()实际上可能并不期望使用ArrayBuffer自变量,因此在这种情况下,我认为这并不是一个“错误”。