# 浏览器文件上传原理

现代网站的前端上传文件的流程主要是利用 input 标签读取到文件,再利用 ajax 将文件的数据发送到后端服务器。

因为 web 程序的运行环境是在浏览器里,在这个流程中 web 应用无法像直接运行在操作系统里的程序那样直接操作用户计算机上的文件。以前的做法是利用 <input type="file"> 把文件放到一个表单中提交。而以前提交表单通常需要刷新页面,现代 web 应用发送数据基本都是利用 ajax 异步提交、获取数据。所以以前利用表单提交数据的方法做法就不太合适了。

为了解决 js 在浏览器环境中运行无法操作用户计算机文件的痛点,浏览器增加了 File API 和 Blob API 以增强 js 访问文件的能力。

# File API

HTML5 在 DOM 的事件对象上添加了 files 数组,这个集合里保存了一组 File 对象,用来标明用户选中的文件。File 对象中的属性保存着选中文件的相关信息。通过 Event 对象的 target 对象里的 files 属性我们可以访问到 File 对象。

<input id="inputBox" type="file" />
const inputBox = document.getElemetById('inputBox');
inputBox.onChange = function(event){
	const selectedFile = event.target.files[0];
    console.log(selectedFile);
}

image-20230115133040378

File 对象部分属性说明

属性作用
name文件名称
size以字节为单位计算的文件大小
type文件的 MIME 类型
lastModified文件最后修改时间的时间戳
lastModifiedDate文件最后修改的时间

# FileReader 类型

FileReader 通常用于读取文件,它是一种异步读取文件的 API。它类似于 XMLHttpRequest ,只不过它是从本地计算机上读取数据,而不是通过网络读取远程计算机上的数据。

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File Blob 对象指定要读取的文件或数据。

const reader = new FileReader();
console.log(reader);

image-20230115134232538

FileReader 部分属性说明

属性说明
error返回读取文件时的错误信息。
readyState表示文件读取的状态。0:reader 已创建;1:读取中;2:读取方法被调用。
result返回读取的文件内容。
onload事件。当文件读取成功时,触发该事件。若 error 事件被触发,则该事件不会被触发。
onloadstart事件。开始读取文件时,触发该事件。
onprogress事件。文件读取时,每过 50ms 触发一次该事件。
onloadend事件。当文件读取完成时,触发该事件,无论文件读取成功与否。
onerror事件。当文件读取失败时,触发该事件。
onabort事件。取消文件读取时触发该事件。

FileReader 类型提供了几个读取文件数据的方法分别用于不同场景。

# readAsText()

readAsText 方法可以将 Blob 或者 File 对象转根据特殊的编码格式转化为内容 (字符串形式),这个方法是异步的,

readAsText 执行完以后会将 readyState 属性改为 2,表示文件读取完成。

函数签名

instance of FileReader.readAsText(blob[, encoding]);

使用实例

const reader = new FileReader();
reader.readAsText(BlobObj, 'utf-8');
reader.onload = (res) => {
    console.log('result', reader.result);
}

# readAsDataURL()

readAsDataURL 方法可以将 Blob 或者 File 对象转化为 base64 编码的字符串,这个方法也是异步的。

readAsDataURL 执行完以后会将 readyState 属性改为 2,表示文件读取完成。

函数签名

instance of FileReader.readAsDataURL(blob);

使用实例

const reader = new FileReader();
reader.readAsDataURL(BlobObj);
reader.onload = (res) => {
    console.log('result', reader.result);
}

# readAsBinaryString ()(废除)

readAsBinaryString 方法可以将 Blob 或者 File 对象转化为原始文件的二进制格式。

readAsBinaryString 执行完以后会将 readyState 属性改为 2,表示文件读取完成。

函数签名

instance of FileReader.readAsBinaryString(blob);

使用实例

const reader = new FileReader();
reader.readAsBinaryString(BlobObj);
reader.onload = (res) => {
    console.log('result', reader.result);
}

# readAsArrayBuffer()

用于替代 readAsBinaryString

# abort()

该方法可以取消 FileReader 的读取操作,触发之后 readyState 为已完成(DONE),值为 2。

函数签名

instanceOfFileReader.abort();

使用实例

const reader = new FileReader();
setTimeout(() => reader.abort(), 100);

# Blob 类型

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。

Blob 表示的不一定是 JavaScript 原生格式的数据。 File 接口基于 Blob ,继承了 blob 的功能并将其扩展以支持用户系统上的文件。

# 实现一个简单的图片上传

  • 实现多张图片上传并限制图片大小小于 2MB
<input id="inputBox" type="file" accept="image/*" multiple="true" />
const inputBox = document.getElementById("inputBox");
function checkImgSize(file){
    const limitSize = 2 * 2 ** 20;
    return file.size < limitSize;
}
inputBox.onchange = function(event){
    const selectedFiles = this.files;
    const isPass = selectedFiles.every(checkImgSize);
    if (!isPass) return alert("请确保每张图片的大小都小于2MB");
    // do something
}
更新于

请我喝[茶]~( ̄▽ ̄)~*

Asuhe 微信支付

微信支付

Asuhe 支付宝

支付宝

Asuhe 贝宝

贝宝