介绍
支持 FileReader
和 <input type="file">
的 Web 浏览器允许用户上传文件。
在本文中,您将探索File
、FileReader
和FileReaderSync
的API。
前提条件
如果您想跟随这篇文章,您将需要:
对JavaScript(方法)(LINK0)、EventListener(LINK1)和Promises(LINK2)的理解将很有帮助
*代码编辑器
*支持File
,FileReader
和FileReaderSync
的现代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});
使用文件``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 Loading
、 Loaded
和 Finished Loading
。
使用FileReaderSync
例如,当浏览器试图读取一个非常大的文件时,我们不希望我们的用户界面停止工作,但是,有一个同步版本的FileReaderSync
称为FileReaderSync
。我们只能在Web Workers中使用FileReaderSync
。
FileReaderSync.readAsArrayBuffer()
FileReaderSync.readAsBinaryString()
FileReaderSync.readAsText()
FileReaderSync.readAsDataURL()
没有事件处理器,因为它是同步的。
结论
在本文中,您探索了File
、FileReader
和FileReaderSync
的API。
花时间检查浏览器对这些功能的支持,以确保它们适用于您的项目的用户。
继续你的学习与其他 Web API。