介绍
支持FileReader
并<input type="file">
允许用户上传文件的Web 浏览器。
在本文中,您将探索File
,FileReader
以及FileReaderSync
API的。
先决条件
如果你想跟随这篇文章,你需要:
- Javascript的理解方法,
EventListener
以及Promises
会有所帮助。 - 一个代码编辑器。
- 一个现代化的网页浏览器,支持
File
,FileReader
和FileReaderSync
。
上传文件
首先,要从用户那里获取文件,我们需要使用一个<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});
使用File
Blob
属性
在现代浏览器中,Files
拥有Blob
属性和功能。这些函数允许我们读取文件。
.text()
将文件转换为流,然后转换为字符串。.stream()
返回一个ReadableStream
..arrayBuffer()
ArrayBuffer
以二进制形式返回包含 blob 数据的 。.slice()
允许您获取文件的切片。
myFile.txt
用一些文本创建一个新文件:
Example file content.
然后,创建一个新file-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()
。
这种方法使用ReadableStream
,TextDecoder()
和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()
:
<!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()
没有事件处理程序,因为它是同步的。
结论
在这篇文章中,您介绍了File
,FileReader
和FileReaderSync
API的。
花点时间检查浏览器对这些功能的支持,以确保它们适用于您的项目用户。
使用其他Web API继续学习。