首页 > 解决方案 > javascript FileReader - 如何分块解析长文件?

问题描述

最初,我在这里进行了加载,就像这样

export function сonvertFilesToByteArray(e) {
  const MAX_FILE_SIZE = 1024 * 1024 * 50; // 50MB
  const files = Object.keys(e.target.files);
  const asyncReadFile = eachFile =>
    new Promise((resolve, reject) => {
      if (e.target.files[eachFile].size > MAX_FILE_SIZE) {
        return reject([{ message: `File ${e.target.files[eachFile].name} too large` }]);
      }
      const reader = new FileReader();
      const targetFileInfo = {
        contentType: e.target.files[eachFile].type,
        filename: e.target.files[eachFile].name,
      };
      reader.readAsArrayBuffer(e.target.files[eachFile]);
      reader.onload = () => {
        resolve({ ...targetFileInfo, body: Array.from(new Uint8Array(reader.result)) });
      };
      reader.onerror = error => reject(error);
    });

  return Promise.all(files.map(asyncReadFile));
}

在常量文件中,我定义了我的文件中有多少个,并对每个文件应用了一个函数。

然后我在组件中获取我的文件

handleFileUpload = (e) => {
    сonvertFilesToByteArray(e)
      .then((result) => {
        runInAction(() => {
          this.files = [
            ...this.files,
            ...result,
          ];
        });
      })
      .catch(err => runInAction(() => {
        this.errors = [...this.errors, err[0].message];
      }));
  }

然后放进去this.files,最后我的this.files样子[{contentType: 'plain/text', filename: 'blabla', body: [123, 456, 23, ...] }]

其中 [123, 456, 23...] 是我的 ArrayBuffer

但是,尽管我使用 Promise.all,但在这种方法中,当加载重量超过 2MB 的文件/文件时,页面被冻结,无法以任何方式与她交互(但我可以滚动)。除了意识到每个文件被分成块时,没有任何想法可以纠正这种情况。好的,我尝试重写代码:With chunks

export function сonvertFilesToByteArray(e) {
  const MAX_FILE_SIZE = 1024 * 1024 * 50; // 50MB
  const files = Object.keys(e.target.files);
  const asyncReadFile = eachFile =>
    new Promise((resolve, reject) => {
      if (e.target.files[eachFile].size > MAX_FILE_SIZE) {
        return reject([{ message: `File ${e.target.files[eachFile].name} too large` }]);
      }
      const file = e.target.files[eachFile];
      let offset = 0;
      console.log(offset, 'offset', file.size, 'size');
      const defaultChunkSize = 64 * 1024; // bytes
      const fileReader = new FileReader();
      const blob = file.slice(offset, offset + defaultChunkSize);
      const isEndOfFile = () => offset >= file.size;
      const testEndOfFile = () => {
        if (isEndOfFile()) {
          console.log('Done reading file');
        }
      };
      fileReader.readAsArrayBuffer(blob);
      fileReader.onloadend = (event) => {
        const target = (event.target);
        if (target.error == null) {
          const result = target.result;
          offset += result.length;
          testEndOfFile();
          console.log(result, 'result');
          resolve(result);
        } else {
          reject(target.error);
        }
      };
    });

  return Promise.all(files.map(asyncReadFile));
}

在这里,我收到文件并对其进行分割。但问题是,如果文件不仅仅是一个块,那么我应该一次又一次地把他从他们那里收集起来。但是在我的情况下如何做到这一点?我怎么都看不懂...

请帮助我:) 以块的形式读取文件并将其作为 ArrayBuffer 接收需要做什么?

标签: javascript

解决方案


推荐阅读