JS中的二进制对象:Blob、File、ArrayBuffer,及转换处理:FileReader、URL.createObjectURL

平时工作和学习中,会遇到一些对二进制对象的操作,总是对Blob、File、FileReader、ArrayBuffer、Buffer、URL.createObjectURL等API傻傻分不清,希望通过这篇文章做一个梳理。

Blob、File、ArrayBuffer都是二进制数据对象,可以使用FileReader、URL.createObjectURL对二进制对象读取转换

1、Blob

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

Blob 表示的不一定是 JavaScript 原生格式的数据。File 接口基于 Blob,继承了 Blob 的功能并扩展

创建 blob 对象

1、new Blob()

var blob = new Blob( array, options )

参数:

  • array:是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的 Array,它将会被放进 Blob;(DOMString可以认为就是字符串,stack overflow有相关问答:What is a DOMString really?

  • options:可以指定两个属性,

    • type,默认值为 "",它代表了将会被放入到 blob 中的数组内容的 MIME 类型
    • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。

示例:

js 复制代码
// 通过buffer创建
const buffer = new ArrayBuffer(8); // 创建了一个 8 字节的缓冲区
const blob1 = new Blob([buffer], { type: "application/octet-stream" });

// 通过字符串创建
const blob2 = new Blob(['<a id="a">hey!</a>'], { type: "text/html" });

// 通过数字创建
const blob3 = new Blob([2], { type: "text/plain" });

// 通过ArrayBufferView创建
const view = new Int8Array(8); // 创建1字节视图
const blob4 = new Blob([view], { type: "application/octet-stream" });

// 通过blob创建blob
const blob5 = new Blob([blob2]);

console.log(blob1, blob2, blob3, blob4, blob5);

2、blob.slice()

var blob = instanceOfBlob.slice([start [, end [, contentType]]]);

参数:

  • start :开始下标,
  • end:结束下标,不包括这个位置
  • contentType:设置type属性,默认值是一个空的字符串。

Blob不可变,不能直接修改,但是可以通过slice把blob分割,创建出新的blob,使用此方法可以对大文件分片上传

示例:

js 复制代码
const blob = new Blob(["FileBlobArrayBuffer"], { type: "text/plain" });

// slice返回一个新的 Blob 对象,它包含了原始 Blob 对象的某一个段的数据。
const b1 = blob.slice(0, 4);
const b2 = blob.slice(4, 8);
const b3 = blob.slice(8);

// text() 方法返回一个 Promise 对象
b1.text().then((t1) => {
  console.log(t1); // 'File'
});
b2.text().then((t2) => {
  console.log(t2); // 'Blob'
});
b3.text().then((t3) => {
  console.log(t3); // 'ArrayBuffer'
});

转换处理 blob 对象

1、FileReader

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

  • readAsText(): BlobFile对象转根据特殊的编码格式异步读取转化为字符, 只有当执行完成后才能够查看到结果,在onloadonloadend 的事件中处理转化后的结果

    示例:

js 复制代码
const obj = { count: 1 };
const blob = new Blob([JSON.stringify(obj)], { type: "application/json" });
// 创建一个文件读取器
const fileRead = new FileReader();
//读取blob对象
fileRead.readAsText(blob);

// 文件成功读取,执行load 事件
fileRead.onload = function (e) {
  console.log(e.target.result); // {"count":1}
  console.log(fileRead.result); // {"count":1}
};

// 文件读取完成,无论成功与否,执行loadend 事件
fileRead.onloadend = function (e) {
  console.log(e.target.result); // {"count":1}
  console.log(fileRead.result); // {"count":1}
};
  • readAsDataURL():BlobFile对象。读取操作完成的时候,readyState会变成已完成DONE,并触发 loadend事件,同时 result 属性将包含一个data:URL 格式的base64编码字符串。

    示例:

html 复制代码
<!-- html -->
<input class="input" type="file" />
<img class="img" src="" height="200" alt="Image preview..." />
js 复制代码
const imgEl = document.querySelector(".img");
const inputEl = document.querySelector(".input");
const fileReader = new FileReader();

inputEl.onchange = function (e) {
  const file = this.files[0];
  // file:File对象,继承自Blob
  if (file) {
    fileReader.readAsDataURL(file);
  }
};

fileReader.onload = function () {
  console.log(fileReader.result); //`data:`URL 格式, base64编码字符串
  imgEl.src = fileReader.result;
};
  • readAsArrayBuffer():BlobFile对象。读取操作完成的时候,readyState会变成已完成DONE,并触发 loadend事件,同时 result 属性将包含一个ArrayBuffer对象数据。

    示例:

js 复制代码
const blob = new Blob(["blob"], { type: "application/json" });
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(blob);
fileReader.onload = function () {
  console.log(this.result); // ArrayBuffer 对象
};

2、URL.createObjectURL

URL.createObjectURL() 静态方法会创建一个 Blob URL,这个新的 URL 表示指定的 File对象或 Blob对象。

这个Blob URL 可以用于img.src作为图片展示,

示例:

html 复制代码
<!-- html -->
  <input class="input" type="file" />
  <img class="img" src="" height="200" alt="Image preview..." />
js 复制代码
const imgEl = document.querySelector(".img");
const inputEl = document.querySelector(".input");

inputEl.onchange = function (e) {
  const file = this.files[0];
  // file : File对象 ,继承自Blob
  if (file) {
    const url = URL.createObjectURL(file);
    console.log(url); // blob:null/b1a2bc4a-1f33-452f-8f88-8b4efee6138d
    imgEl.src = url;
  }
};

也能作为二进制数据下载链接

示例:

html 复制代码
    <!-- html -->
    <input class="input" type="file" />
    <img class="img" src="" height="200" alt="Image preview..." />
    <a class="download">下载图片</a>
js 复制代码
const imgEl = document.querySelector(".img");
const inputEl = document.querySelector(".input");
const aEl = document.querySelector(".download");

inputEl.onchange = function (e) {
  const file = this.files[0];
  // file : File对象 ,继承自Blob
  if (file) {
    const url = URL.createObjectURL(file);
    console.log(url); // blob:null/b1a2bc4a-1f33-452f-8f88-8b4efee6138d
    imgEl.src = url; // 图片显示

    aEl.download = "js.jpg";
    aEl.href = url; // 下载链接
  }
};

3、Response

Response对象可以使用new Response创建,但通常更可能遇到的情况是,其他的 API 操作返回了一个 Response 对象。通过new Response(blob)传入一个blob对象,可以通过以下实例方法进行转换:

  • arrayBuffer() :返回一个被解析为 ArrayBuffer格式的 Promise 对象。
  • blob() :并返回一个被解析为 Blob格式的 Promise 对象。
  • json() :并返回一个被解析为 json的 Promise 对象。
  • text() :并返回一个被解析为 文本 的 Promise 对象。

2、File

File对象 通常产生于<input> 元素上选择文件后返回的 FileList对象,或者自由拖放操作生成的 DataTransfer 对象。

File 对象继承自Blob,是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。比如说, FileReader, URL.createObjectURL(), 及 XMLHttpRequest.send() 都能处理 BlobFile

1、<input>元素选择文件

html 复制代码
<!-- html-->
<input class="input" type="file" />
js 复制代码
const inputEl = document.querySelector(".input");
inputEl.onchange = function (e) {
  const file = this.files[0];
  console.log(file);
};

2、拖放文件

html 复制代码
  <!--  -->
  <div class="drop-wrapper"></div>
js 复制代码
const dropEl = document.querySelector(".drop-wrapper");
dropEl.ondragover = (e) => {
  e.preventDefault(); // 阻止默认行为,否则浏览器会新开一个标签页
};

dropEl.ondrop = (e) => {
  e.preventDefault(); // 阻止默认行为
  console.log(e);
  const files = e.dataTransfer.files;
  console.log(files);
};

3、转换处理File

File 接口没有定义任何方法,它继承了Blob接口,可以调用Blob 的实例方法,同样可以使用 FileReader, URL.createObjectURL()等方法转换 File

3、ArrayBuffer

详解见阮一峰老师的 《ECMAScript 6 入门》ArrayBuffer

相关推荐
梦境之冢29 分钟前
axios 常见的content-type、responseType有哪些?
前端·javascript·http
racerun32 分钟前
vue VueResource & axios
前端·javascript·vue.js
J总裁的小芒果1 小时前
THREE.js 入门(六) 纹理、uv坐标
开发语言·javascript·uv
m0_548514771 小时前
前端Pako.js 压缩解压库 与 Java 的 zlib 压缩与解压 的互通实现
java·前端·javascript
AndrewPerfect1 小时前
xss csrf怎么预防?
前端·xss·csrf
Calm5501 小时前
Vue3:uv-upload图片上传
前端·vue.js
浮游本尊1 小时前
Nginx配置:如何在一个域名下运行两个网站
前端·javascript
m0_748239831 小时前
前端bug调试
前端·bug
m0_748232921 小时前
[项目][boost搜索引擎#4] cpp-httplib使用 log.hpp 前端 测试及总结
前端·搜索引擎
新中地GIS开发老师1 小时前
《Vue进阶教程》(12)ref的实现详细教程
前端·javascript·vue.js·arcgis·前端框架·地理信息科学·地信