JavaScript 文件对象详解

简介: 在浏览器中操作文件,多数情况下用到的是 File 对象,从 <input type='file' /> 元素获取,进而继续操作(例如将选择的图片展示在页面上,用ajax将文件上传至服务器等)。这里介绍在浏览器中操作文件的相关API.

在浏览器中操作文件,多数情况下用到的是 File 对象,从 <input type='file' /> 元素获取,进而继续操作(例如将选择的图片展示在页面上,用ajax将文件上传至服务器等)。这里介绍在浏览器中操作文件的相关API.

File 对象继承自 Blob 对象,先看看 Blob 对象。

1. Blob 对象

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。

Blob构造函数 Blob(array[, options])

  • array 是一个由ArrayBuffer, ArrayBufferView, Blob, string 等对象构成的 Array ,或者其他类似对象的混合体,它将会被放进 Blob。string会被编码为UTF-8。
  • options 是一个可选的对象,它可能会指定如下两个属性:
    • type,默认值为 "",它代表了将会被放入到blob中的数组内容的MIME类型
    • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持blob中保存的结束符不变。

示例:

var content1 = ['This is my firt trip to an island'];
var blob1 = new Blob(content, {type: 'text/plain'});
var content2 = {name: 'Alice', age: 23};
var blob2 = new Blob([JSON.stringify(content2, null, 2)], {type: 'application/json'});
复制代码
AI 代码解读

Blob实例属性

属性名称 读/写 描述
size 只读 Blob 对象中所包含数据的大小(字节)。
type 只读 一个字符串,表明该Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。例如 "image/png".

示例:

var content = ['<div id="box"><p class="pra">a paragraph</p></div>'];
var blob = new Blob(content, {type: 'text/html'});
console.log(blob.size); // 50
console.log(blob.type); // text/html
复制代码
AI 代码解读

Blob实例方法

  • slice([start[, end[, contentType]]])

slice 方法接收三个可选参数,startend 都是数值,表示截取的范围,contentType 指定截取的内容的 MIME 类型。返回一个新的 Blob对象。

var blob = new Blob(['This is an example of Blob slice method'], {type: 'text/plain'});
console.log(blob.size); // 39
var newBlob = blob.slice(10, 20, 'text/plain');
console.log(newBlob.size); // 10
复制代码
AI 代码解读

Blob 对象中读取内容可以使用 FileReader. 下文会介绍。

2. File 对象

File构造函数

我们接触的多数关于 File 的操作都是读取,js也为我们提供了手动创建 File 对象的构造函数:File(bits, name[, options])

  • bits (required) ArrayBuffer,ArrayBufferView,Blob,或者 Array[string] — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。。

  • name [String] (required) 文件名称,或者文件路径.

  • options [Object] (optional) 选项对象,包含文件的可选属性。可用的选项如下:

    • type: string, 表示将要放到文件中的内容的MIME类型。默认值为 '' 。
    • lastModified: 数值,表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()。

示例:

var file1 = new File(['text1', 'text2'], 'test.txt', {type: 'text/plain'});
AI 代码解读

根据已有的 blob 对象创建 File 对象:

var file2 = new File([blob], 'test.png', {type: 'image/png'});
AI 代码解读

File实例属性

File 对象的实例内容不可见,但是有以下属性可以访问:

属性名称 读/写 描述
name 只读 返回文件的名称.由于安全原因,返回的值并不包含文件路径 。
type 只读 返回 File 对象所表示文件的媒体类型(MIME)。例如 PNG 图像是 "image/png".
lastModified 只读 number, 返回所引用文件最后修改日期,自 1970年1月1日0:00 以来的毫秒数。
lastModifiedDate 只读 Date, 返回当前文件的最后修改日期,如果无法获取到文件的最后修改日期,则使用当前日期来替代。

示例:

<input type="file" id='file'>
AI 代码解读
document.getElementById('file').addEventListener('change', function(event){
  const file = this.files[0];
  if (file) {
    console.log(file.name);
    console.log(file.size);
    console.log(file.lastModified);
    console.log(file.lastModifiedDate);
  }
});
AI 代码解读

备注: 基于当前的实现,浏览器不会实际读取文件的字节流,来判断它的媒体类型。它基于文件扩展来假设;将PNG 图像文件的后缀名重命名为 .txt,那么读取的该文件的 type 属性值为 "text/plain", 而不是 "image/png" 。而且,file.type 仅仅对常见文件类型可靠。例如图像、文档、音频和视频。不常见的文件扩展名会返回空字符串。开发者最好不要依靠这个属性,作为唯一的验证方案。

File实例方法

  • slice([start[, end[, contentType]]])

File 对象没有定义额外的方法,由于继承了 Blob 对象,也就继承了 slice方法,用法同上文 Blobslice 方法。

FileReader, URL.createObjectURL(), createImageBitmap(), 及 XMLHttpRequest.send() 都能处理 Blob 和 File。

3. FileReader 对象

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

其中 File 对象可以是来自用户在一个 <input> 元素上选择文件后返回的 FileList, 也可以来自拖放操作生成的 DataTransfer 对象,还可以是来自在一个 HTMLCanvasElement 上执行 mozGetAsFile() 方法后返回结果。

FileReader构造函数

var reader = new FileReader()

构造函数不需要传入参数,返回一个 FileReader 的实例。FileReader 继承 EventTarget对象。

FileReader实例属性

属性名称 读/写 描述
error 只读 DOMException 的实例,表示在读取文件时发生的错误 。
result 只读 文件的内容,该属性仅在读取操作完成后(load)后才有效,格式取决于读取方法
readyState 只读 表示读取文件时状态的数字

备注: readeyState的取值如下:

常量名 描述
0 EMPTY 还没有加载任何数据
1 LOADING 数据正在被加载
2 DONE 已完成全部的读取请求.

使用示例:

var reader = new FileReader();
console.log(reader.error);       // null
console.log(reader.result);      // null
console.log(reader.readyState);  // 0
console.log(reader.EMPTY);       // 0
console.log(reader.LOADING);     // 1
console.log(reader.DONE);        // 2
AI 代码解读

EMPTYLOADINGDONE 这三个属性同时存在于 FileReader 和它的的原型对象上,因此实例上有这三个属性,FileReader 对象本身也有这三个属性:

console.log(FileReader.EMPTY);   // 0
console.log(FileReader.LOADING); // 1
console.log(FileReader.DONE);    // 2
AI 代码解读

FileReader事件

文件的读取是一个异步的过程,和 XMLHttpRequest 对象一样,在读取操作过程中会触发一系列事件。

事件名称 描述 使用示例
abort 读取操作被中断时触发。 reader.onabort = function(event) {}
error 在读取操作发生错误时触发。 reader.onerror = function(event) {}
load 读取操作完成时触发。 reader.addEventListener('load', function(event) {})
loadstart 读取操作开始时触发。 reader.onloadstart = function(event) {}
loadend 读取操作结束时(要么成功,要么失败)触发。 reader.onloadend = function(event) {}
progress 在读取Blob时触发。 reader.onprogress = function(event) {}

FileReader实例方法

FileReader 的实例具有以下可操作的方法:

方法名称 描述 使用示例
abort() 手动终止读取操作,只有当 readyState 为 1 时才能调用,调用后,readyState 值为 2 reader.abort()
readAsArrayBuffer(blob) 读取指定的 BlobFile 对象。读取操作完成后(触发loadend事件),result属性将包含一个 ArrayBuffer 对象表示所读取的文件的数据。 reader.readAsArrayBuffer(blob)
readAsDataURL(blob) 读取指定的 BlobFile 对象。读取操作完成后(触发loadend事件),result属性将包含一个 data:URL 格式的字符串(base64编码) reader.readAsArrayBuffer(file)
readAsBinaryString(blob) 已废弃,用 readAsArrayBuffer 代替 --
readAsText(blob[, encoding]) 将 Blob 或者 File 对象转根据特殊的编码格式转化为内容(字符串形式), 默认编码是 utf-8 reader.readAsArrayBuffer(blob)

读取本地图片示例:

<input type="file" id='file' accept="image/png, image/jpg, image/jpeg, image/gif" />><br />>
<img src="" alt="Image preview...">
AI 代码解读
var preview = document.querySelector('img');
var reader  = new FileReader();
reader.addEventListener("load", function () {
  preview.src = reader.result;
}, false);
document.getElementById('file').addEventListener('change', function (event) {
  var file = this.files[0];
  if (file) {
    reader.readAsDataURL(file);
  }
});
AI 代码解读

读取多个文件示例 - CodePen

dataURL是base64编码的数据格式,展示类型为字符串,形如: data:image/jpeg;base64,/9j/4QXERXhpZgAATU...

dataURL 转为 blob对象:

function dataURLToBlob (dataurl) {
  let arr = dataurl.split(',');
  let mime = arr[0].match(/:(.*?);/)[1];
  let bstr = atob(arr[1]);
  let n = bstr.length;
  let u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}
AI 代码解读

结合上例,根据已有的 <img> 对象创建一个 File 对象:

reader.addEventListener("load", function () {
  preview.src = reader.result;
  var blob = dataURLToBlob(reader.result);
  var newFile = new File([blob], 'test.jpeg', {type: blob.type});
  console.log(newFile.name); // test.jpeg
  console.log(newFile.type);
  console.log(newFile.size);
}, false);
AI 代码解读

URL.createObjectURL

将图片文件转换成 data:URL 格式供 <img> 元素展示,除了使用 fileReader.readAsDataURL外,还可以使用 URL.createObjectURL方法。 URL.createObjectURL(blob) 方法返回一个 blob: 开头的字符串,指向文件在内存中的地址。

<input type="file" id='file' accept="image/png, image/jpg, image/jpeg, image/gif" /><br />
<img src="" alt="Image preview...">
AI 代码解读
var preview = document.querySelector('img');
document.getElementById('file').addEventListener('change', function (event) {
  var file = this.files[0];
  if (file) {
    preview.src = URL.createObjectURL(file);
  }
});
AI 代码解读

综合实例

综合以上,可以实现一个简单的粘贴图片并显示的功能。HTML5提供的内容编辑功能,可以粘贴部分图片,例如从网页上复制的图片。但是使用截图工具截取的图片无法粘贴显示,而且从网页上复制的图片会带有原来的样式,其图片url也是原来图片的指向。我们使用以下代码可以统一这两种粘贴操作,实现统一的效果。

<div id="comment" contenteditable></div>
AI 代码解读
#comment{
  border: 1px solid #ccc;
  min-height: 500px;
  padding: 10px;
}
#comment:focus {
  border-color: #ccc;
  outline: none;
}
.img-paste {
  max-width: 100%;
}
AI 代码解读
var comment = document.getElementById('comment');
comment.addEventListener('paste', function(event) {
  console.log(event);
  var item = event.clipboardData.files[0];
  if (item && /image/.test(item.type)) {
    var img = new Image();
    img.src = URL.createObjectURL(item);
    img.className = 'img-paste';
    this.appendChild(img);
    event.preventDefault();
  }
}, false);
AI 代码解读

实例效果可以查看这里

参考链接



原文发布时间为:2018年06月29日

原文作者:Mr-dang

本文来源: 掘金  如需转载请联系原作者
相关文章
【Java进阶】详解JavaScript的BOM(浏览器对象模型)
总的来说,BOM提供了一种方式来与浏览器进行交互。通过BOM,你可以操作窗口、获取URL、操作历史、访问HTML文档、获取浏览器信息和屏幕信息等。虽然BOM并没有正式的标准,但大多数现代浏览器都实现了相似的功能,因此,你可以放心地在你的JavaScript代码中使用BOM。
56 23
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
js文件的入口代码及需要入口代码的原因
js文件的入口代码及需要入口代码的原因
83 0
Next.js 实战 (六):如何实现文件本地上传
这篇文章介绍了在Next.js中如何实现文件上传到本地的方法。文章首先提到Next.js官方文档中没有提供文件上传的实例代码,因此开发者需要自行实现,通常有两种思路:使用Node.js原生上传或使用第三方插件如multer。接着,文章选择了使用Node.js原生上传的方式来讲解实现过程,包括如何通过哈希值命名文件、上传到指定目录以及如何分类文件夹。然后,文章展示了具体的实现步骤,包括编写代码来处理文件上传,并给出了代码示例。最后,文章通过一个效果演示说明了如何通过postman模拟上传文件,并展示了上传后的文件夹结构。
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
63 1
JavaScript中对象的数据拷贝
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
js中函数、方法、对象的区别
js中函数、方法、对象的区别
88 2
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
98 1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等