文件类型对象的汇总
一、ArrayBuffer 对象
ArrayBuffer 对象表示一段二进制数据,用来模拟内存里面的数据。通过这个对象,JavaScript 可以读写二进制数据。这个对象可以看作内存数据的表达。
1、创建 ArrayBuffer 对象
var buffer = new ArrayBuffer(8);
buffer.byteLength // 8
上面代码中,实例对象 buffer 占用 8 个字节。可通过 ArrayBuffer 的 byteLength 属性byteLength 查看实例占用的内存长度(单位字节)
2、ArrayBuffer.slice() 方法
用来复制一部分内存。它接受两个整数参数,分别表示复制的开始位置(从0开始)和结束位置(复制时不包括结束位置),如果省略第二个参数,则表示一直复制到结束。
var buf1 = new ArrayBuffer(8);
var buf2 = buf1.slice(0);
二、Blob 对象
Blob(Binary Large Object)对象表示一个二进制文件的数据内容,比如一个图片文件的内容就可以通过 Blob 对象读写。
1、创建 Blob 对象
var aBlob = new Blob( array, options );
参数:
array
:一个由 ArrayBuffer、ArrayBufferView、Blob、DOMString 等字符串或二进制对象构成的数组,表示新生成的 Blob 实例对象的内容。options
:是一个可选的配置对象,可指定两个属性:type
:表示数据的 MIME 类型,默认值为 ""。endings
:默认值为 "transparent",用于指定包含行结束符 \n 的字符串如何被写入。
举个例子:
var data = { name: "Guangzhou" };
var blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
/* 输出:
Blob {
size: 20,
type: 'application/json',
__proto__: Blob
}
size 表示数据的大小(以字节为单位)
type 是 MIME 类型的字符串。
*/
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
2、size 和 type 属性
- size:返回数据的大小。
- type:返回数据的类型。
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, { type: 'text/html' });
myBlob.size // 32
myBlob.type // "text/html"
3、Blob.slice() 方法
用来拷贝原来的数据,返回的也是一个 Blob 实例。
var blob = instanceOfBlob.slice([start [, end [, contentType]]]);
参数:
- start(可选)起始的字节位置,默认为 0。
- end(可选)结束的字节位置,默认为 size 属性的值,该位置本身将不包含在拷贝的数据之中。
- contentType(可选)新实例的数据类型,默认为空字符串。
4、请求得到 Blob 对象
AJAX 请求时,如果指定 responseType 属性为 blob,下载下来的就是一个 Blob 对象。
function getBlob(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.onload = function () {
callback(xhr.response);
}
xhr.send(null);
}
上面代码中,xhr.response
拿到的就是一个 Blob 对象。
5、根据 Blob 生成 URL
浏览器允许使用 URL.createObjectURL() 方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。
这个 URL 以 blob://
开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。这一点与 data://URL
(URL 包含实际数据)和 file://URL
(本地文件系统里面的文件)都不一样。
var droptarget = document.getElementById('droptarget');
droptarget.ondrop = function (e) {
var files = e.dataTransfer.files;
for (var i = 0; i < files.length; i++) {
var type = files[i].type;
if (type.substring(0, 6) !== 'image/')
continue;
var img = document.createElement('img');
img.src = URL.createObjectURL(files[i]);
// blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641
img.onload = function () {
this.width = 100;
document.body.appendChild(this);
URL.revokeObjectURL(this.src);
}
}
}
上面代码通过为拖放的图片文件生成一个 URL,产生它们的缩略图,从而使得用户可以预览选择的文件。
浏览器处理 Blob URL 就跟普通的 URL 一样,如果 Blob 对象不存在,返回 404 状态码;如果跨域请求,返回 403 状态码。Blob URL 只对 GET 请求有效,如果请求成功,返回 200 状态码。由于 Blob URL 就是普通 URL,因此可以下载。
三、FileList 对象
FileList 对象是一个类数组对象,代表一组选中的文件,每个成员都是一个 File 实例,主要出现在两个场合:
- 文件控件节点
<input type="file">
的 files 属性,返回一个 FileList 实例。 - 拖拉一组文件时,目标区的
DataTransfer.files
属性,返回一个 FileList 实例。
<input id="fileItem" type="file">
var files = document.getElementById('fileItem').files;
files instanceof FileList // true
上面代码中,文件控件的 files 属性是一个 FileList 实例。
1、属性及方法
FileList 的实例属性主要是 length,表示包含多少个文件。
FileList 的实例方法主要是 item(),用来返回指定位置的实例。它接受一个整数作为参数,表示位置的序号(从零开始)。但由于 FileList 的实例是一个类似数组的对象,可以直接用方括号运算符,即 myFileList[0]
等同于 myFileList.item(0)
,所以一般用不到 item() 方法。
2、获取文件信息
文件选择器 <input type="file">
用来让用户选取文件。出于安全考虑,浏览器不允许脚本自行设置这个控件的 value 属性,即文件必须是用户手动选取的,而非脚本指定。一旦用户选好了文件,脚本就可以读取这个文件。
文件选择器返回一个 FileList 对象,该对象是一个类似数组的成员,每个成员都是一个 File 实例对象。File 实例对象是一个特殊的 Blob 实例,增加了 name 和 lastModifiedDate 属性。
<input type="file" accept="image/*" multiple onchange="fileinfo(this.files)" />
function fileinfo(files) {
for (var i = 0; i < files.length; i++) {
var f = files[i];
console.log(
f.name, /* 文件名,不含路径 */
f.size, /* 文件大小,Blob 实例属性 */
f.type, /* 文件类型,Blob 实例属性 */
f.lastModifiedDate /* 文件的最后修改时间 */
);
}
}
除了文件选择器,拖放 API 的 dataTransfer.files
返回的也是一个 FileList 对象,它的成员因此也是 File 实例对象。
四、File 对象
File 对象代表一个文件,用来读写文件信息。它继承了 Blob 对象,或者说是一种特殊的 Blob 对象,所有可以使用 Blob 对象的场合都可以使用它。
最常见的是表单的文件上传控件 <input type="file">
,用户选中文件以后,浏览器就会生成一个数组,里面是每一个用户选中的文件,它们都是 File 实例对象。
<input id="fileItem" type="file">
var file = document.getElementById('fileItem').files[0];
file instanceof File // true
上面代码中,file 是用户选中的第一个文件,它是 File 的实例。
1、创建 File 对象
new File(array, name [, options])
var file = new File(
['foo'],
'foo.txt',
{
type: 'text/plain',
}
);
参数:
array(必须)
:一个数组,成员可以是二进制对象或字符串,表示文件的内容。name(必须)
:字符串,表示文件名或文件路径。options(可选)
:配置对象,设置实例的属性,可以设置两个属性:type
:字符串,表示实例对象的 MIME 类型,默认值为空字符串。lastModified
:时间戳,表示上次修改的时间,默认为 Date.now()。
2、File 对象的属性
File.lastModified
:最后修改时间。File.name
:文件名或文件路径。File.size
:文件大小(单位字节)File.type
:文件的 MIME 类型。
var myFile = new File([], 'file.bin', {
lastModified: new Date(2018, 1, 1),
});
myFile.lastModified // 1517414400000
myFile.name // "file.bin"
myFile.size // 0
myFile.type // ""
上面代码中,由于 myFile 的内容为空,也没有设置 MIME 类型,所以 size 属性等于 0,type 属性等于空字符串。
File 对象没有自己的实例方法,由于继承了 Blob 对象,因此可以使用 Blob 的实例方法 slice()
五、FileReader 对象
FileReader 对象用于读取 File 对象或 Blob 对象所包含的文件内容。
1、创建 FileReader 对象
var reader = new FileReader();
2、FileReader 对象的属性
FileReader.error
:读取文件时产生的错误对象。FileReader.readyState
:表示读取文件时的当前状态的整数。0 表示尚未加载任何数据,1 表示数据正在加载,2 表示加载完成。FileReader.result
:读取完成后的文件内容,可能是字符串,也可能是一个 ArrayBuffer 实例。FileReader.onabort
:abort 事件(用户终止读取操作)的监听函数。FileReader.onerror
:error 事件(读取错误)的监听函数。FileReader.onload
:load 事件(读取操作完成)的监听函数,通常在这个函数里面使用 result 属性,拿到文件内容。FileReader.onloadstart
:loadstart 事件(读取操作开始)的监听函数。FileReader.onloadend
:loadend 事件(读取操作结束)的监听函数。FileReader.onprogress
:progress 事件(读取操作进行中)的监听函数。
举个例子:
<input type="file" onchange="onChange(event)">
function onChange(event) {
var file = event.target.files[0];
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result)
};
reader.readAsText(file);
}
上面代码中,每当文件控件发生变化,就尝试读取第一个文件。如果读取成功(load 事件发生),就打印出文件内容。
3、FileReader 对象的方法
FileReader.abort()
:终止读取操作,readyState 属性将变成 2。FileReader.readAsText()
:读取完成后,result 属性将返回文件内容的文本字符串。该方法的第一个参数是代表文件的 Blob 实例,第二个参数是可选的,表示文本编码,默认为 UTF-8。FileReader.readAsArrayBuffer()
:以 ArrayBuffer 的格式读取文件,读取完成后 result 属性将返回一个 ArrayBuffer 实例。FileReader.readAsDataURL()
:读取完成后,result 属性将返回一个 Data URL 格式(Base64 编码)的字符串,代表文件内容。对于图片文件,这个字符串可以用于<img>
元素的 src 属性。注意,这个字符串不能直接进行 Base64 解码,必须把前缀data:*/*;base64,
从字符串里删除后再进行解码。FileReader.readAsBinaryString()
:读取完成后,result 属性将返回原始的二进制字符串。
举个例子:
<input type="file" onchange="previewFile()">
<img src="" height="200">
function previewFile() {
var preview = document.querySelector('img');
var file = document.querySelector('input[type=file]').files[0];
var reader = new FileReader();
reader.addEventListener('load', function () {
preview.src = reader.result;
}, false);
if (file) {
reader.readAsDataURL(file);
}
}
上面代码中,用户选中图片文件以后,脚本会自动读取文件内容,然后作为一个 Data URL 赋值给 <img>
元素的 src 属性,从而把图片展示出来。
六、文件对象的转换
1、Blob 与 File
File 和 Blob 都用来表示类文件对象,File 继承自 Blob 对象,是一种特殊的 Blob 对象,同时 File 又有自己独特的属性和方法。
1-1、Blob 转 File
function blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date();
theBlob.name = fileName;
return theBlob;
}
2、Blob 与 ArrayBuffer
Blob 对象通常用来读写文件,与 ArrayBuffer 的区别在于,它用于操作二进制文件,而 ArrayBuffer 用于操作内存。
2-1、Blob 转 ArrayBuffer
使用 FileReader 的 readAsArrayBuffer()
方法,可以把 Blob 对象转换为 ArrayBuffer 对象:
var blob = new Blob(["\x01\x02\x03\x04"]),
fileReader = new FileReader(),
array;
fileReader.onload = function () {
array = this.result;
console.log("Array contains", array.byteLength, "bytes.");
};
fileReader.readAsArrayBuffer(blob);
2-2、ArrayBuffer 转 Blob
使用 Blob 构造函数,如 new Blob([new Uint8Array(data)]);
可以把 ArrayBuffer 对象转换为 Blob 对象:
var array = new Uint8Array([0x01, 0x02, 0x03, 0x04]);
var blob = new Blob([array]);
3、Blob/File 与 dataURL
URL.createObjectURL
的一个替代方法是,将 Blob 转换为 base64 编码的字符串。
3-1、Blob/File 转 dataURL
// 将传入的 File/Blob 对象转为 base64 的 dataURL
function file2DataUrl(file, callback) {
var reader = new FileReader();
reader.onload = function () {
callback(reader.result);
};
reader.readAsDataURL(file);
}
// input type = file 的表单获取
file.oninput = function () {
console.log(this.files[0])
file2DataUrl(this.files[0], function (img) {
console.log(img)
})
}
如果图片较大,图片的色彩层次比较丰富,则不适合使用这种方式,因为该图片经过 base64 编码后的字符串非常大,会明显增大 HTML 页面的大小,从而影响加载速度。
3-2、dataURL 转 Blob/File
function dataURLtoBlob(dataurl) {
var arr = dataurl.split(','),
mime = arr[0].match(/:(.*?);/)[1],
// 全局变量的 atob 函数,用于解码 base64 编码
bstr = atob(arr[1]),
n = bstr.length,
// 创建一个 8 位无符号整型数组,数组项取值范围是 0~255
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], {
type: mime
})
}
dataURLtoBlob('data:image/png;base64,XXXXXXXX')