【问题标题】:FileReader().readAsArrayBuffer(file) result gets stuck after first loaded fileFileReader().readAsArrayBuffer(file) 结果在第一次加载文件后卡住
【发布时间】:2019-06-10 17:18:08
【问题描述】:

我正在使用此代码生成一个md5 哈希字符串,用作我存储中的文件名。我读取文件(图像)内容并使用md5 库计算哈希。

在我读取第一个文件后,FileReader() API 的方法 readAsArrayBuffer(file) 的结果不知何故卡住了。

CodeSandBox: 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

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);

【问题讨论】:

    标签: javascript reactjs browser filereader arraybuffer


    【解决方案1】:

    我不是 100% 确定发生了什么,但它看起来是您正在使用的 md5() 库的问题。如果您将ArrayBuffer 实例显式转换为Uint8Array,那么事情并不奇怪:

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

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

    您的 md5() 实际上可能并不期望 ArrayBuffer 参数,所以在这种情况下,我认为这并不是一个真正的“错误”。

    【讨论】:

    • 谢谢! md5 文档说它需要 String or Buffer。你认为这是问题所在吗?
    • @cbdev420 我不确定;我所知道的是,当你给它一个类型化的数组时它工作得很好。它给了我与您在此处发布的内容中显示的完全相同的非真正哈希值,所以这让我认为它正在从 ArrayBuffer 实例中散列一些特定的可重复字节集;我不知道如何或为什么。
    • @cbdev420 好吧也许;像图像数据这样的非文本数据的问题是可能存在无法识别的 UTF-16 序列,这可能会导致问题。我不知道。制作一个新阵列不应该那么昂贵。它不必分配内存,因为缓冲区已经存在。
    • 我猜你是对的。关于 ArrayBuffer 的 MDN 文档说:您不能直接操作 ArrayBuffer 的内容;相反,您创建一个类型化数组对象或 DataView 对象,它以特定格式表示缓冲区,并使用它来读取和写入缓冲区的内容。
    • 好吧Uint8Array 似乎有效,所以它是一个强有力的竞争者:) 我怀疑它是否重要,只要给定类型似乎有效(比如,如果你得到某种运行时异常,这很重要当然)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 2022-10-18
    • 2019-10-05
    相关资源
    最近更新 更多