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

介绍

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

在本文中,您将探索FileFileReaderFileReaderSync的API。

前提条件

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

对JavaScript(方法)(LINK0)、EventListener(LINK1)和Promises(LINK2)的理解将很有帮助 *代码编辑器 *支持File,FileReaderFileReaderSync的现代Web浏览器

上传一个文件

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

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

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

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

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

对于处理上传的更大控制,您可以使用JavaScript而不是HTML <form>来提交文件:

1let file = document.getElementById('input').files[0];
2let formData = new FormData();
3
4formData.append('file', file);
5fetch('/upload/image', {method: "POST", body: formData});

這種方法是用於使用 FormDatafetch

使用文件``blob属性

在现代浏览器中,文件具有Blob的属性和功能,这些功能使我们能够读取文件。

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

创建一个新的myFile.txt文件,包含一些文本:

1[label myFile.txt]
2Example file content.

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

 1[label file-blob-example.html]
 2<!DOCTYPE html>
 3<html>
 4<body>
 5  <input type="file" id="input" />
 6
 7  <script>
 8    const streamToText = async (blob) => {
 9      const readableStream = await blob.getReader();
10      const chunk = await readableStream.read();
11
12      return new TextDecoder('utf-8').decode(chunk.value);
13    };
14
15    const bufferToText = (buffer) => {
16      const bufferByteLength = buffer.byteLength;
17      const bufferUint8Array = new Uint8Array(buffer, 0, bufferByteLength);
18
19      return new TextDecoder().decode(bufferUint8Array);
20    };
21
22    document.getElementById('input').addEventListener('change', function(e) {
23      let file = document.getElementById('input').files[0];
24
25      (async () => {
26        const fileContent = await file.text();
27
28        console.log('.text()', fileContent);
29
30        const fileContentStream = await file.stream();
31
32        console.log('.stream()', await streamToText(fileContentStream));
33
34        const buffer = await file.arrayBuffer();
35
36        console.log('.buffer()', bufferToText(buffer));
37
38        const fileSliceBlob = file.slice(0, file.length);
39        const fileSliceBlobStream = await fileSliceBlob.stream();
40
41        console.log('.slice() and .stream()', await streamToText(fileSliceBlobStream));
42      })();
43    });
44  </script>
45</body>
46</html>

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

這種方法使用的是 ReadableStream, TextDecoder()Uint8Array()

应用FileReader生命周期和方法

有6个主要事件附加到FileReader:

  • loadstart: 在我们开始加载文件时会发生火灾
  • progress: 在记忆中阅读blob时会发生火灾
  • abort: 当我们呼叫 .abort
  • error: 在出现错误时会发生火灾
  • load: 在阅读成功时会发生火灾
  • loadend: 在加载文件时会发生火灾,如果错误或 abort 没有被呼叫或如果加载开始新的读取

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

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

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

 1[label filereader-example.html]
 2<!DOCTYPE html>
 3<html>
 4<head>
 5  <style>
 6    body {
 7      background: #000;
 8      color: white;
 9    }
10
11    #progress-bar {
12      margin-top: 1em;
13      width: 100vw;
14      height: 1em;
15      background: red;
16      transition: 0.3s;
17    }
18  </style>
19</head>
20<body>
21  <input type="file" id="input" />
22  <progress value="0" max="100" id="progress-bar"></progress>
23  <div id="status"></div>
24  <script>
25    const changeStatus = (status) => {
26      document.getElementById('status').innerHTML = status;
27    }
28
29    const setProgress = (e) => {
30      const fr = e.target;
31      const loadingPercentage = 100 * e.loaded / e.total;
32
33      document.getElementById('progress-bar').value = loadingPercentage;
34    }
35
36    const loaded = (e) => {
37      const fr = e.target;
38      var result = fr.result;
39
40      changeStatus('Finished Loading!');
41      console.log('Result:', result);
42    }
43
44    const errorHandler = (e) => {
45      changeStatus('Error: ' + e.target.error.name);
46    }
47
48    const processFile = (file) => {
49      const fr = new FileReader();
50
51      fr.readAsDataURL(file);
52      fr.addEventListener('loadstart', changeStatus('Start Loading'));
53      fr.addEventListener('load', changeStatus('Loaded'));
54      fr.addEventListener('loadend', loaded);
55      fr.addEventListener('progress', setProgress);
56      fr.addEventListener('error', errorHandler);
57      fr.addEventListener('abort', changeStatus('Interrupted'));
58    }
59
60    document.getElementById('input').addEventListener('change', (e) => {
61      const file = document.getElementById('input').files[0];
62
63      if (file) {
64        processFile(file);
65      }
66    });
67  </script>
68</body>
69</html>

在您的 Web 浏览器中打开 filereader-example.html,并将 myFile.txt 文件添加到 input. 当文件被处理时,屏幕上会显示进度栏。如果文件被成功加载,则会显示 Start LoadingLoadedFinished Loading

使用FileReaderSync

例如,当浏览器试图读取一个非常大的文件时,我们不希望我们的用户界面停止工作,但是,有一个同步版本的FileReaderSync称为FileReaderSync。我们只能在Web Workers中使用FileReaderSync

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

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

结论

在本文中,您探索了FileFileReaderFileReaderSync的API。

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

继续你的学习与其他 Web API

Published At
Categories with 技术
Tagged with
comments powered by Disqus