Skip to content

前端二进制2

ArrayBuffer

ArrayBuffer对象代表储存二进制数据的一段内存,它不能直接读写,只能通过视图进行操作。

// 创建一个长度为 16 的 buffer 它会分配一个 16 字节(byte)的连续内存空间,并用 0 进行预填充。
const buffer1 = new ArrayBuffer(16);
复制代码

TypedArray

TypedArray是一组构造函数,一共包含九种类型,每一种都是一个构造函数。

TypedArray的构造函数接受三个参数,第一个ArrayBuffer(其实还可以是数组、视图这里不细说)对象,第二个视图开始的字节号(默认0),第三个视图结束的字节号(默认直到本段内存区域结束)。

名称占用字节描述
Int8Array18位有符号整数
Uint8Array18位无符号整数
Uint8ClampedArray18位无符号整型固定数组(数值在0~255之间)
Int16Array216位有符号整数
Uint16Array216位无符号整数
Int32Array432 位有符号整数
Uint32Array432 位无符号整数
Float32Array432 位 IEEE 浮点数
Float64Array864 位 IEEE 浮点数
// Uint8Array —— 将 ArrayBuffer 中的每个字节视为 0 到 255 之间的单个数字(每个字节是 8 位)。这称为 “8 位无符号整数”。
// Uint16Array —— 将每 2 个字节视为一个 0 到 65535 之间的整数。这称为 “16 位无符号整数”。
// Uint32Array —— 将每 4 个字节视为一个 0 到 4294967295 之间的整数。这称为 “32 位无符号整数”。
// Float64Array —— 将每 8 个字节视为一个 5.0x10-324 到 1.8x10308 之间的浮点数。

const uint8 = new Uint8Array(buffer1);
const uint16 = new Uint16Array(buffer1);
const uint32 = new Uint32Array(buffer1);
const float64 = new Float64Array(buffer1);
复制代码

DataView

DataView 就是一种更灵活的视图,DataView视图支持除Uint8ClampedArray以外的八种类型。DataView比使用TypedArray更方便,只需要简单的创建一次就能进行各种转换。

// 可以转成各种格式
const dataView1 = new DataView(buffer1);
console.log(dataView1);
console.log(dataView1.getUint8(0));
console.log(dataView1.getUint16(0));
console.log(dataView1.getUint32(0));
console.log(dataView1.getFloat64(0));
复制代码

Blob

Blob 对象表示一个不可变、原始数据的类文件对象。

// 构造函数
const blob = new Blob(array, options)
复制代码
  • array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成的数组,DOMStrings会被编码为UTF-8。
  • options 是一个可选,它可能会指定如下两个属性:
    • type,默认值为 "",内容的MIME类型。
    • endings,默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入。 它是以下两个值中的一个: "native",代表行结束符会被更改为适合宿主操作系统文件系统的换行符,或者 "transparent",代表会保持blob中保存的结束符不变
const blob1 = new Blob(['hello randy'], { type: "text/plain" });
复制代码

实例属性、方法

属性

const blob = new Blob(["hello", "randy"], { type: "text/plain" });
// 输出的对象有如下属性
// size: 10;
// type: "text/plain";
console.log(blob);
复制代码

方法

  • slice()Blob 中截取一部分并返回一个新的 Blob(用法同数组的 slice)
  • arrayBuffer() 返回一个以二进制形式展现的 promise
  • stream() 返回一个ReadableStream对象
  • text() 返回一个文本形式的 promise
// 转成stream
console.log(blob.stream());

// 转成Arraybuffer
blob.arrayBuffer().then((res) => {
  console.log(res);
});

// 转成文本
blob.text().then((res) => {
  console.log(res);
});
复制代码

blob url

简单的理解一下就是将一个fileBlob类型的对象转为UTF-16的字符串,并保存在当前操作的document下,存储在内存中。

生成blob url使用的方法是URL.createObjectURL(file/blob)。清除方式只有页面unload()事件或者使用URL.revokeObjectURL(objectURL)手动清除 。

这在前端下载中经常会用到。

export const downloadFile = async (params, fileName) => {
  // 我们使用axios设置接口返回类型 responseType: "blob", 所以这里从后端返回的是blob。
  const results = await download(params);
  
  const a = document.createElement("a");
  a.download = fileName + ".xlsx";
  // 生成blob url。这里可以使用Blob对象或者File对象
  a.href = window.URL.createObjectURL(results);
  a.style.display = "none";
  document.body.appendChild(a);
  a.click();
  // 释放内存
  window.URL.revokeObjectURL(a.href);
  document.body.removeChild(a);
};
复制代码

File

File 描述文件信息的一个对象,可以让 JavaScript 访问文件信息。File 继承于 Blob

const file = new File(array, name[, options])
复制代码
  • array 是一个由ArrayBuffer, ArrayBufferView, Blob, DOMString 等对象构成,DOMStrings会被编码为UTF-8。
  • name 表示文件名称,或者文件路径。
  • options 是一个可选,它可能会指定如下两个属性:
    • type,默认值为 "",内容的MIME类型。
    • lastModified: 数值,表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()。

实例属性、方法

属性

  • type 类型 常见的MIME 类型
  • size 大小、单位为字节
  • name 文件名称
  • lastModified 最后修改时间(时间戳)
  • lastModifiedDate 最后修改时间
const file1 = new File(["文件对象"], "test", { type: "text/plain" });
// 输出的对象有如下属性
// lastModified: 1640589621358
// lastModifiedDate: Mon Dec 27 2021 15:20:21 GMT+0800 (中国标准时间) {}
// name: "test"
// size: 12
// type: "text/plain"
// webkitRelativePath: ""
console.log(file1);
复制代码

方法

  • slice()Blob 中截取一部分并返回一个新的 Blob(用法同数组的 slice)
  • arrayBuffer() 返回一个以二进制形式展现的 promise
  • stream() 返回一个ReadableStream对象
  • text() 返回一个文本形式的 promise
// 转成stream
console.log(file1.stream());

// 转成Arraybuffer
file1.arrayBuffer().then((res) => {
  console.log(res);
});

// 转成文本
file1.text().then((res) => {
  console.log(res);
});
复制代码

Base64

定义

Base64是一种编码格式,在前端经常会碰到,格式是 data:[<mediatype>][;base64],<data>

除了使用工具进行Base64编码外,js还内置了两个方法能进行字符串的Base64的编码和解码。

const str1 = "hello randy";

// 编码
const b1 = window.btoa(str1);
console.log(b1); // aGVsbG8gcmFuZHk=

// 解码
const str2 = window.atob(b1);
console.log(str2); // hello randy
复制代码

Blob转Base64

const blob = new Blob(["hello", "randy"], { type: "text/plain" });
const fileReader = new FileReader();
fileReader.readAsDataURL(blob);
fileReader.onload = () => {
  console.log(fileReader.result); // "data:text/plain;base64,aGVsbG9yYW5keQ=="
};
复制代码

优点

  1. 可以将二进制数据(比如图片)转化为可打印字符,方便传输数据。
  2. 对数据进行简单的加密,肉眼是安全的。
  3. 如果是在html或者css处理图片,可以减少http请求。

缺点

  1. 内容编码后体积变大, 至少大1/3。因为是三字节变成四个字节,当只有一个字节的时候,也至少会变成三个字节。
  2. 编码和解码需要额外工作量。

FileReader

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

属性

属性描述
FileReader.error一个DOMException,表示在读取文件时发生的错误 。
FileReader.result返回文件的内容。只有在读取操作完成后,此属性才有效,返回的数据的格式取决于是使用哪种读取方法来执行读取操作的。
FileReader.readyState表示FileReader状态的数字。0 还没有加载任何数据。1 数据正在被加载。2 已完成全部的读取请求。

方法

需要注意的是 ,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在 result属性中。

方法名描述
FileReader.abort()中止读取操作。在返回时,readyState 属性为 DONE。
FileReader.readAsArrayBuffer()将读取的内容转成ArrayBuffer。
FileReader.readAsBinaryString()将读取的内容转成二进制数据。
FileReader.readAsDataURL()将读取的内容转成并将其编码为 base64 的 data url。 格式是 data:[<mediatype>][;base64],<data>
FileReader.readAsText()将数据读取为给定编码(默认为 utf-8 编码)的文本字符串。

事件

事件描述
FileReader.onabort处理 abort 事件。该事件在读取操作被中断时触发。
FileReader.onerror处理 error 事件。该事件在读取操作发生错误时触发。
FileReader.onload处理 load 事件。该事件在读取操作完成时触发。
FileReader.onloadstart处理 loadstart 事件。该事件在读取操作开始时触发。
FileReader.onloadend处理 loadend 事件。该事件在读取操作结束时(要么成功,要么失败)触发。
FileReader.onprogress处理 progress 事件。该事件在读取Blob时触发。

例子

const blob3 = new Blob(["hello", "randy"], { type: "text/plain" });

const fileReader = new FileReader();

fileReader.readAsDataURL(blob3);

fileReader.onload = () => {
  console.log(fileReader);
  // 通过fileReader获取结果
  // fileReader.result 是结果(如果成功)
  // fileReader.error 是 error(如果失败)。
};
复制代码

相互转换

Blob和File的互相转换

Blob转File

const blob1 = new Blob(["blob文件"], { type: "text/plain" });
// blob转file
const file2 = new File([blob1], "test2", { type: blob1.type });
console.log("file2: ", file2);
复制代码

File转Blob

const file1 = new File(["文件对象"], "test", { type: "text/plain" });
// file转blob
const blob2 = new Blob([file1], { type: file1.type });
console.log("blob2: ", blob2);
复制代码

File、Blob、img转Base64

Blob转Base64

// Blob转Base64
const blob = new Blob(["hello", "randy"], { type: "text/plain" });

const fileReader = new FileReader();

fileReader.readAsDataURL(blob);

fileReader.onload = () => {
  console.log(fileReader.result); // "data:text/plain;base64,aGVsbG9yYW5keQ=="
};
复制代码

File转Base64

// File转Base64
const file1 = new File(["文件对象"], "test", { type: "text/plain" });

const fileReader = new FileReader();

fileReader.readAsDataURL(file1);

fileReader.onload = () => {
  console.log(fileReader); // "data:text/plain;base64,5paH5Lu25a+56LGh"
};
复制代码

img转Base64

// 本地图片转base64,注意链接是本地链接不能是网络地址。
const img2base64 = (imgUrl) => {
  let image = new Image();
  image.src = imgUrl;
  return new Promise((resolve) => {
    image.onload = () => {
      let canvas = document.createElement("canvas");
      canvas.width = image.width;
      canvas.height = image.height;
      var context = canvas.getContext("2d");
      context.drawImage(image, 0, 0, image.width, image.height);
      let dataUrl = canvas.toDataURL("image/png");
      resolve(dataUrl);
    };
  });
};

img2base64("../vue2/src/assets/logo.png").then((res) => {
  console.log(res);
});
复制代码

Base64转Blob、File

Base64转Blob

function dataURLtoBlob(dataurl) {
  // `data:[<mediatype>][;base64],<data>`
  var arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}
复制代码

Base64转File

function dataURLtoFile(dataurl, filename) {
  //将base64转换为文件
  var arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}
复制代码

参考文章

JavaScript中 FileReader 对象详解

Blob、ArrayBuffer、File、FileReader和FormData的区别

初探 Js 中的 Blob、ArrayBuffer、File 、FileRender、FormData

Released under the MIT License.