如何使用 JavaScript FileReader API 读取和处理文件

介绍

支持FileReader<input type="file">允许用户上传文件的Web 浏览器

在本文中,您将探索FileFileReader以及FileReaderSyncAPI的。

先决条件

如果你想跟随这篇文章,你需要:

  • Javascript的理解方法EventListener以及Promises会有所帮助。
  • 一个代码编辑器。
  • 一个现代化的网页浏览器,支持FileFileReaderFileReaderSync

上传文件

首先,要从用户那里获取文件,我们需要使用一个<input>元素:

<input id="input" type="file" />

此代码将让用户从他们的机器上传文件。

以下是使用 HTML 上传文件的示例<form>

<form enctype="multipart/form-data" action="/upload" method="post">
  <input id="input" type="file" />
</form>

为了更好地控制处理上传,您可以使用 JavaScript 而不是 HTML<form>来提交文件:

let file = document.getElementById('input').files[0];
let formData = new FormData();

formData.append('file', file);
fetch('/upload/image', {method: "POST", body: formData});

这种方法使用FormDatafetch

使用File Blob属性

在现代浏览器中,Files拥有Blob属性和功能。这些函数允许我们读取文件。

  • .text() 将文件转换为流,然后转换为字符串。
  • .stream()返回一个ReadableStream.
  • .arrayBuffer()ArrayBuffer以二进制形式返回包含 blob 数据的 。
  • .slice() 允许您获取文件的切片。

myFile.txt用一些文本创建一个新文件:

我的文件.txt
Example file content.

然后,创建一个新file-blob-example.html文件:

文件-blob-example.html
<!DOCTYPE html>
<html>
<body>
  <input type="file" id="input" />

  <script>
    const streamToText = async (blob) => {
      const readableStream = await blob.getReader();
      const chunk = await readableStream.read();

      return new TextDecoder('utf-8').decode(chunk.value);
    };

    const bufferToText = (buffer) => {
      const bufferByteLength = buffer.byteLength;
      const bufferUint8Array = new Uint8Array(buffer, 0, bufferByteLength);

      return new TextDecoder().decode(bufferUint8Array);
    };

    document.getElementById('input').addEventListener('change', function(e) {
      let file = document.getElementById('input').files[0];

      (async () => {
        const fileContent = await file.text();

        console.log('.text()', fileContent);

        const fileContentStream = await file.stream();

        console.log('.stream()', await streamToText(fileContentStream));

        const buffer = await file.arrayBuffer();

        console.log('.buffer()', bufferToText(buffer));

        const fileSliceBlob = file.slice(0, file.length);
        const fileSliceBlobStream = await fileSliceBlob.stream();

        console.log('.slice() and .stream()', await streamToText(fileSliceBlobStream));
      })();
    });
  </script>
</body>
</html>

file-blob-example.html在 Web 浏览器中打开并将myFile.txt文件添加input. 在您的web开发者控制台,您将看到文件的内容读出来使用.text().stream().buffer(),和.slice()

这种方法使用ReadableStreamTextDecoder()Uint8Array()

应用FileReader生命周期和方法

FileReader 有 6 个主要事件:

  • loadstart: 当我们开始加载文件时触发。
  • progress: 在内存中读取 blob 时触发。
  • abort: 当我们调用时触发.abort
  • error: 发生错误时触发。
  • load:读取成功时触发。
  • loadend: 加载文件时触发,如果错误或中止没有被调用,或者加载开始新的读取。

要开始加载我们的文件,我们有四种方法:

  • readAsArrayBuffer(file): 将文件或 blob 作为数组缓冲区读取。一个用例是将大文件发送给 Service Worker。
  • readAsBinaryString(file): 以二进制字符串形式读取文件
  • readAsText(file, format): 将文件读取为 USVString(几乎像一个字符串),你可以指定一个可选的格式。
  • readAsDataURL(file):这将返回一个 URL,您可以在其中访问文件的内容,它是 Base64 编码的并准备发送到您的服务器

创建一个新filereader-example.html文件,使用readAsDataURL()

文件阅读器-example.html
<!DOCTYPE html>
<html>
<head>
  <style>
    body {
      background: #000;
      color: white;
    }

    #progress-bar {
      margin-top: 1em;
      width: 100vw;
      height: 1em;
      background: red;
      transition: 0.3s;
    }
  </style>
</head>
<body>
  <input type="file" id="input" />
  <progress value="0" max="100" id="progress-bar"></progress>
  <div id="status"></div>
  <script>
    const changeStatus = (status) => {
      document.getElementById('status').innerHTML = status;
    }

    const setProgress = (e) => {
      const fr = e.target;
      const loadingPercentage = 100 * e.loaded / e.total;

      document.getElementById('progress-bar').value = loadingPercentage;
    }

    const loaded = (e) => {
      const fr = e.target;
      var result = fr.result;

      changeStatus('Finished Loading!');
      console.log('Result:', result);
    }

    const errorHandler = (e) => {
      changeStatus('Error: ' + e.target.error.name);
    }

    const processFile = (file) => {
      const fr = new FileReader();

      fr.readAsDataURL(file);
      fr.addEventListener('loadstart', changeStatus('Start Loading'));
      fr.addEventListener('load', changeStatus('Loaded'));
      fr.addEventListener('loadend', loaded);
      fr.addEventListener('progress', setProgress);
      fr.addEventListener('error', errorHandler);
      fr.addEventListener('abort', changeStatus('Interrupted'));
    }

    document.getElementById('input').addEventListener('change', (e) => {
      const file = document.getElementById('input').files[0];

      if (file) {
        processFile(file);
      }
    });
  </script>
</body>
</html>

filereader-example.html在 Web 浏览器中打开并将myFile.txt文件添加input. 处理文件时,屏幕上会出现一个进度条。如果成功加载,它会显示'Start Loading''Loaded''Finished Loading'

使用 FileReaderSync

FileReader是一个异步 API,因为我们不想在读取文件时阻塞主线程。例如,当浏览器试图读取一个非常大的文件时,我们不希望我们的用户界面停止工作。但是,有一个同步版本的FileReader调用FileReaderSync我们只能FileReaderSync在 Web Workers 中使用Web worker 有自己的线程,所以他们不会阻塞主线程。FileReaderSync使用相同的方法FileReader

  • FileReaderSync.readAsArrayBuffer()
  • FileReaderSync.readAsBinaryString()
  • FileReaderSync.readAsText()
  • FileReaderSync.readAsDataURL()

没有事件处理程序,因为它是同步的。

结论

在这篇文章中,您介绍了FileFileReaderFileReaderSyncAPI的。

花点时间检查浏览器对这些功能的支持,以确保它们适用于您的项目用户。

使用其他Web API继续学习

觉得文章有用?

点个广告表达一下你的爱意吧 !😁