文件相关
JavaScript 在处理文件、二进制数据和数据转换时,提供了一系列的 API 和对象,比如 File、Blob、FileReader、ArrayBuffer、Base64、Object URL 和 DataURL。每个概念在不同场景中都有重要作用。下面的内容我们将会详细学习每个概念及其在实际应用中的用法。
1.MIME类型
MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的标准,用来表示文档、文件或字节流的性质和格式。
MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。
浏览器通常使用 MIME 类型(而不是文件扩展名)来确定如何处理URL,因此 We b服务器在响应头中添加正确的 MIME 类型非常重要。如果配置不正确,浏览器可能会无法解析文件内容,网站将无法正常工作,并且下载的文件也会被错误处理。
1.1 语法
MIME由类型与子类型两个字符串中间用/分隔而组成,不允许有空格
type/subtype- type:表示可以被分多个子类的独立类别
- subtype:表示细分后的每个类型。
MIME类型对大小写不敏感,但是传统写法都是小写。
两种主要的 MIME 类型在默认类型中扮演了重要的角色:
- text/plain 表示文本文件的默认值。
- application/octet-stream 表示所有其他情况的默认值
1.2 常见MIME类型
- 超文本标记语言文本 .html:text/html
- 普通文本 .txt: text/plain
- RTF 文本 .rtf: application/rtf
- GIF 图形 .gif: image/gif
- JPEG 图形 .jpeg、.jpg: image/jpeg
- au 声音文件 .au: audio/basic
- MIDI 音乐文件 mid、.midi: audio/midi、audio/x-midi
- RealAudio 音乐文件 .ra、.ram: audio/x-pn-realaudio
- MPEG 文件 .mpg、.mpeg: video/mpeg
- AVI 文件 .avi: video/x-msvideo
- GZIP 文件 .gz: application/x-gzip
- TAR 文件 .tar: application/x-tar
| 类型 | 描述 | 典型示例 |
|---|---|---|
text | 表明文件是普通文本,理论上是人类可读 | text/plain, text/html, text/css, text/javascript |
image | 表明是某种图像。不包括视频,但是动态图(比如动态gif)也使用image类型 | image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon, image/vnd.microsoft.icon |
audio | 表明是某种音频文件 | audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav |
video | 表明是某种视频文件 | video/webm, video/ogg |
application | 表明是某种二进制数据 | application/octet-stream, application/pkcs12, application/vnd.mspowerpoint, application/xhtml+xml, application/xml, application/pdf |
具体可查看MIME类型
2.Blob对象
2.1 概念
在 JavaScript 中,Blob(Binary Large Object)对象用于表示不可变的、原始的二进制数据。
它可以存储任何类型的数据,比如文件、图片、音频、视频、甚至是纯文本
Blob 提供了一种高效的方式来操作数据文件,而不需要将数据全部加载到内存中,这在处理大型文件或二进制数据时非常有用。
2.2 构造函数
Blob是一个对象,使用需要使用new关键字调用Blob()构造函数创建实例
const blob = new Blob([blobParts][, options]);- blobParts: 可选,一个可迭代对象
- 比如
Array,包含ArrayBuffer、TypedArray、DataView、Blob、字符串或者任意这些元素的混合 - 这些元素将会被放入
Blob中。字符串应该是格式良好的Unicode
- 比如
- options: 一个可选的对象,可以设置 type(MIME 类型)和 endings(用于表示换行符)。
- type:可选,将会被存储到 blob 中的数据的
MIME类型。默认值是空字符("")。 - endings:如果数据是文本,那么如何解释其中的换行符(
\n)。默认值transparent会将换行符复制到 blob 中而不会改变它们。要将换行符转换为主机系统的本地约定,请指定值native。
- type:可选,将会被存储到 blob 中的数据的
简单使用:
const blob =new Blob(['hello world'], {type: 'text/plain'});
console.log(blob)
2.3 实例属性
size
只读, Blob 对象中所包含数据的大小(字节)。
const blob =new Blob(['阿珍爱上了阿强,在一个有星星的夜晚'], {type: 'text/plain'});
console.log(blob.size) // 51type
只读,一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。
const blob =new Blob(['阿珍爱上了阿强,在一个有星星的夜晚'], {type: 'text/plain'});
console.log(blob.type) // text/plain2.4 实例方法
text()
该方法将 Blob 的内容读取 UTF-8 格式的字符串。它返回一个 Promise,解析为文本数据
const blob = new Blob(['阿珍爱上了阿强,在一个有星星的夜晚'], { type: 'text/plain' })
blob.text().then(text => console.log(text)) // 阿珍爱上了阿强,在一个有星星的夜晚slice()
可在一个Blob中截取数据,并返回一个新的Blob
slice()
slice(start)
slice(start, end)
slice(start, end, contentType)参数:
- start:需要截取内容的开始字节索引
- 默认值是 0
- 若传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。例如,-10 将会是
Blob的倒数第十个字节 - 如果你传入的
start的长度大于源Blob的长度,那么返回的将会是一个长度为0并且不包含任何数据的一个Blob对象。
- end:需要截取内容的结束字节索引,不包含此索引的数据
- 默认值就是它的原始长度
size。 - 如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。举例来说,-10 将会是
Blob的倒数第十个字节。
- 默认值就是它的原始长度
- contentType:给新的
Blob赋予一个新的MIME内容类型。这将会把它的type属性设为被传入的值。它的默认值是一个空字符串。
返回值:一个新的Blob对象,它包含了调用该方法的原始 blob 对象所包含数据的指定子集。原始的 blob 不会被改变。
const blob = new Blob(['阿珍爱上了阿强,在一个有星星的夜晚'], { type: 'text/plain' })
const blob1 = blob.slice()
blob1.text().then(res => console.log(res)) //阿珍爱上了阿强,在一个有星星的夜晚
const blob2 = blob.slice(6)
blob2.text().then(res => console.log(res)) //爱上了阿强,在一个有星星的夜晚
const blob3 = blob.slice(6, 12)
blob3.text().then(res => console.log(res)) //爱上
const blob4 = blob.slice(6, 12, 'utf-8')
blob4.text().then(res => console.log(res)) //爱上TIP
使用slice()截取汉字时,一个汉字需要3个字节,这是由于 UTF-8 是一种变长编码方式,不同的字符根据其Unicode值的范围采用不同的字节数:
- 1 个字节:用于ASCII字符(例如英文字母、数字等)
- 2 个字节:用于一些常用的拉丁字符和其他字符
- 3 个字节:用于大多数汉字及其他常用符号
- 4 个字节:用于一些较为冷门的字符
因此,在使用 Blob 对象等处理汉字字符串时,通常会发现每个汉字占用 3 个字节的情况。这个设计使得UTF-8能够向后兼容ASCII,同时有效地支持多种语言和符号。
arrayBuffer()
该方法将 Blob 的内容读取为 ArrayBuffer 对象,适合处理二进制数据。它返回一个 Promise,解析为 ArrayBuffer 数据。
const blob = new Blob(["阿珍爱上了阿强,在一个有星星的夜晚"], { type: "text/plain" });
blob.arrayBuffer().then((buffer) => {
console.log(buffer);
});
stream()
该方法将 Blob 的数据作为一个 ReadableStream 返回,允许你以流的方式处理数据,适合处理大文件。
const blob = new Blob(["阿珍爱上了阿强,在一个有星星的夜晚"], { type: "text/plain" });
const stream = blob.stream();
console.log(stream);
2.5 Blob使用场景
Blob 对象在很多场景中非常有用,尤其是在 Web 应用中处理文件、图片或视频等二进制数据时。以下是一些常见的使用场景:
生成文件下载
可以通过 Blob 创建文件并生成下载链接供用户下载文件。
<body>
<button>Download</button>
<script>
const downLoad = () => {
const blob = new Blob(['This is a test file.'], { type: 'text/plain' })
const url = URL.createObjectURL(blob) // 创建一个 Blob URL
const a = document.createElement('a')
a.href = url
a.download = 'test.txt'
a.click()
URL.revokeObjectURL(url) // 释放 URL 对象
}
document.querySelector('button').addEventListener('click', downLoad)
</script>
</body>上传文件
可以通过 FormData 对象将 Blob 作为文件上传到服务器:
const formData = new FormData();
formData.append("file", blob, "example.txt");
fetch("/upload", {
method: "POST",
body: formData,
}).then((response) => {
console.log("File uploaded successfully");
});读取文件
通过 FileReader API 可以将 Blob 对象读取为不同的数据格式。举例来说,你可以将 Blob 读取为图片并显示在页面上:
<body>
<input type="file" id="fileInput" accept="image/*" />
<img src="" alt="" id="imageContainer">
<script>
const fileInput = document.getElementById("fileInput");
const imageContainer = document.getElementById("imageContainer");
fileInput.addEventListener("change", function (event) {
const file = event.target.files[0];
if (file && file.type.startsWith("image/")) {
const reader = new FileReader();
reader.onload = function (e) {
const img = document.querySelector("#imageContainer");
img.src = e.target.result;
};
reader.readAsDataURL(file);
} else {
alert("请选择一个有效的图片文件。");
}
});
</script>
</body>3.File对象
File 是 JavaScript 中代表文件的数据结构,它继承自 Blob 对象,包含文件的元数据(如文件名、文件大小、类型等)。
File继承Blob对象

3.1 创建File对象
File 对象通常由用户通过 <input type="file"> 选择文件时创建
event.target.files是一个FileList对象,也是个数组,上传的文件在数组第一个元素这中
<body>
<input type="file" id="fileInput" />
<script>
const fileInput = document.getElementById("fileInput");
fileInput.addEventListener("change", function (event) {
const file = event.target.files[0];
console.log("文件名:", file.name);
console.log("文件类型:", file.type);
console.log("文件大小:", file.size);
});
</script>
</body>当<input/>具有multiple属性时,可以多选文件,此时event.target.files中会包含每个文件的数据
<body>
<input type="file" id="fileInput" multiple/>
<script>
const fileInput = document.getElementById("fileInput");
fileInput.addEventListener("change", function (event) {
const file = event.target.files;
console.log(file)
});
</script>
</body>也可以使用 JavaScript 构造函数手动创建。
以下是File构造函数,用于创建File对象
3.2 构造函数
new File(fileBits, fileName)
new File(fileBits, fileName[, options])参数:
- fileBits:一个可迭代对象,例如一个ArrayBuffer、TypedArray、DataView、Blob、具有字符串或任何此类元素的组合的数组,将被放入
File内。请注意,这里的字符串被编码为 UTF-8,与通常的 JavaScript UTF-16 字符串不同。 - fileName:表示文件名或文件路径的字符串。
- options:可选,包含文件可选属性的选项对象。可用选项如下:
- type:可选,表示将放入文件的内容的 MIME 类型的字符串。默认值为
""。 - endings:可选,如果数据是文本,如何解释内容中的换行符(
\n)。默认值transparent将换行符复制到 blob 中而不更改它们。要将换行符转换为主机系统的本机约定,指定值为native - lastModified:可选,一个数字,表示 Unix 时间纪元与文件上次修改时间之间的毫秒数。默认值为调用
Date.now()返回的值。
- type:可选,表示将放入文件的内容的 MIME 类型的字符串。默认值为
const file = new File(["Hello, world!"], "hello-world.txt", {
type: "text/plain",
});
console.log(file);
blob转file
const blob = new Blob(['hello world'], { type: 'text/plain' })
const file = new File([blob], 'test.txt')
const url = URL.createObjectURL(blob)
window.open(url)3.3 实例属性
因为File继承自Blob,所以包含size和type属性
lastModified
只读属性,提供文件的上次修改日期,作为自 Unix 纪元(1970 年 1 月 1 日午夜)以来的毫秒数。没有已知最后修改日期的文件返回当前日期。
lastModifiedDate
只读属性,返回文件的最后修改日期。没有已知最后修改日期的文件则返回当前日期。
name
只读属性返回由 File 对象表示的文件的名称。由于安全原因,该属性并不包含文件路径。
webkitRelativePath
只读属性,它规定了文件的路径,相对于用户在 <input> 元素中选择的目录
3.4 实例方法
File本身没有方法,但继承了 Blob 对象的方法,因此可以使用一些 Blob 对象的方法来处理文件数据。
text():读取文件内容,并将其作为文本返回(这是 Blob 的方法,但可以用于 File 对象)。
const file = new File(['阿珍爱上了阿强,在一个有星星的夜晚'], 'hello-world.txt', {
type: 'text/plain',
})
file.text().then(res=>console.log(res)) // 阿珍爱上了阿强,在一个有星星的夜晚slice():从文件中获取一个子部分数据,返回一个新的 Blob 对象。
const file = new File(['阿珍爱上了阿强,在一个有星星的夜晚'], 'hello-world.txt', {
type: 'text/plain',
})
file.slice(0, 12).text().then(res=>console.log(res)) // 阿珍爱上arrayBuffer():将文件内容读取为 ArrayBuffer(用于处理二进制数据)。
const file = new File(['阿珍爱上了阿强,在一个有星星的夜晚'], 'hello-world.txt', {
type: 'text/plain',
})
file.arrayBuffer().then((buffer) => {
console.log(buffer); // 输出文件的 ArrayBuffer
});
stream():返回一个 ReadableStream 对象,可以通过流式读取文件内容。
const stream = file.stream();4.FileList
FileList 接口表示由 HTML的<input/>元素的files属性返回的该类型的对象,
这使你可以访问使用 <input type="file"> 元素选择的文件列表。它还用于使用拖放 API 中放入 Web 内容中的文件列表;
<body>
<input type="file" id="fileInput" accept="image/*" />
<script>
const input = document.getElementById('fileInput')
input.addEventListener('change', event => {
const files = event.target.files
console.log(files)
})
</script>
</body>
给<input/>元素添加mutiple属性,可以多选属性
<body>
<input type="file" id="fileInput" accept="image/*" multiple />
<script>
const input = document.getElementById('fileInput')
input.addEventListener('change', event => {
const files = event.target.files
console.log(files)
})
</script>
</body>
5.FileReader对象
FileReader 允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数。
5.1 构造函数
const fileReader=new FileReader()5.2 实例属性
error
返回读取文件时的错误信息
readyState
提供 FileReader 读取操作时的当前状态。
- 0:还没有加载任何数据,对应静态属性
FileReader.EMPTY - 1:数据正在被加载,对应静态属性
FileReader.LOADING - 2:已完成全部的读取请求,对应静态属性
FileReader.DONE
result
返回文件的内容。只有在读取操作完成后,此属性才有效
值为一个字符串或者一个ArrayBuffer(取决于使用哪种读取方法)
读取方法为以下的readAsArrayBuffer、readAsDataURL、readAsText
5.3 实例方法
abort()
中止FileReader的读取操作,触发之后 readyState 为已完成(DONE)
readAsArrayBuffer()
用于开始读取指定 Blob或 File的内容。当读取操作完成时,readyState属性变为 DONE,并触发 loadend事件。此时,result属性包含一个表示文件数据的 ArrayBuffer。
readAsArrayBuffer(blob)参数:
- blob:从中读取的
Blob或File对象。
readAsDataURL()
用于开始读取指定 Blob或 File的内容。当读取操作完成时,readyState属性变为 DONE,并触发 loadend事件。此时,result属性包含作为 data: URL 的数据,将文件的数据表示为 base64 编码字符串。
readAsDataURL(blob)参数:
- blob:从中读取的
Blob或File对象。
readAsText()
用于开始读取指定 Blob或 File的内容。当读取操作完成时,readyState属性变为 DONE,并触发 loadend事件。并且 result属性包含表示文件内容的文本字符串。
readAsText(blob)
readAsText(blob, encoding)参数:
- blob:从中读取的
Blob或File对象。 - encoding:指定用于返回数据的编码的字符串。如果未指定此参数,则默认情况下假定为 UTF-8。
5.4 事件
事件类型
以下事件的事件对象都为ProgressEvent,继承自Event
除了继承自Event的属性,还有如下几个属性
| 属性 | 描述 |
|---|---|
| ProgressEvent.lengthComputable | 只读,一个布尔标志,指示底层进程要完成的总工作量以及已完成的工作量是否可计算。换句话说,它表明进展是否可衡量。 |
| ProgressEvent.loaded | 只读,一个 64 位无符号整数值,指示底层进程已执行的工作量。完成工作的比率可以通过将 total 除以该属性的值来计算。使用 HTTP 下载资源时,仅计算 HTTP 消息的正文,不包括标头和其他开销。 |
| ProgressEvent.total | 只读,一个 64 位无符号整数,表示底层进程正在执行的工作总量。使用 HTTP 下载资源时,这是 Content-Length(消息正文的大小),不包括标头和其他开销。 |
abort
abort 事件在读取被中止时触发:例如因为程序调用了FileReader.abort()方法。
此事件不可取消且不会冒泡。
const fileReader=new FileReader()
fileReader.addEventListener("abort", (event) => {});
fileReader.onabort = (event) => {};error
error 事件在由于错误(例如,因为文件未找到或不可读)导致读取失败时触发。
此事件不可取消且不会冒泡。
const fileReader=new FileReader()
fileReader.addEventListener("error", (event) => {});
fileReader.onerror = (event) => {};load
load 事件在成功读取文件时触发。
const fileReader=new FileReader()
fileReader.addEventListener("load", (event) => {});
fileReader.onload = (load) => {};一般在此事件中处理读取的数据
<body>
<input type="file" id="fileInput" accept="image/*" multiple />
<img src="" alt="" >
<script>
const input = document.getElementById('fileInput')
input.addEventListener('change', event => {
const file = event.target.files[0]
const reader = new FileReader()
reader.onload = e => {
const img = document.querySelector('img')
img.src = e.target.result
}
reader.readAsDataURL(file)
})
</script>
</body>loadend
loadend 事件在文件读取完成(无论成功与否)时触发。
此事件不可取消且不会冒泡。
const fileReader=new FileReader()
fileReader.addEventListener("loadend", (event) => {});
fileReader.onloadend = () => {};loadstart
loadstart 事件在文件读取操作开始时触发。
const fileReader=new FileReader()
fileReader.addEventListener("loadstart", (event) => {});
fileReader.onloadstart = (event) => {};progress
progress 事件在 FileReader 读取数据时定期触发。
此事件不可取消且不会冒泡。
const fileReader=new FileReader()
fileReader.addEventListener("progress", (event) => {});
fileReader.onprogress = (event) => {};此事件可以实现读取进度展示
input.addEventListener('change', event => {
const file = event.target.files[0]
const reader = new FileReader()
reader.onprogress = event => {
const progress = (event.loaded / event.total) * 100
console.log(progress)
}
reader.readAsDataURL(file)
})6.URL相关
createObjectURL()
createObjectURL() 可以给指定的Blob或File对象创建一个url,从而可以在网页上展示,或者文件的下载
URL.createObjectURL(object)参数:
- object:用于创建
URL的File、Blob或MediaSource对象。
新窗口预览图片
<body>
<input type="file" id="fileInput" accept="image/*" />
<script>
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
const url=URL.createObjectURL(file);
open(url);
})
</script>
</body>TIP
每次调用 createObjectURL() 时,都会创建一个新的对象 URL,即使已经为同一个对象创建了一个 URL。当不再需要这些对象时,必须通过调用 URL.revokeObjectURL()来释放它们。
revokeObjectURL()
你完成对对象 URL 的使用后,请调用此方法,让浏览器知道无需再保持对文件的引用。
const blob = new Blob(['hello world'], { type: 'text/plain' })
const url = URL.createObjectURL(blob)
URL.revokeObjectURL(url)