Skip to main content

文件类型对象的汇总

一、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:一个由 ArrayBufferArrayBufferView、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')