Skip to content

Blob

FileBlobFileReaderArrayBufferBase64 关系图。

图片

Blob

Blob 全称为 binary large object ,即二进制大对象,它是 JavaScript 中的一个对象,表示原始的类似文件的数据。下面是 MDN 中对 Blob 的解释:

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

实际上,Blob 对象是包含有只读原始数据的类文件对象。简单来说,Blob 对象就是一个 不可修改 的二进制文件。

Blob构造函数参数

javascript
new Blob(array, options);
new Blob(array, options);
  • array:由 ArrayBuffer、ArrayBufferView、Blob、DOMString 等对象构成的,将会被放进 Blob;
  • options:可选的 BlobPropertyBag 字典,它可能会指定如下两个属性
    • type:默认值为 "",表示将会被放入到 blob 中的数组内容的 MIME 类型
    • endings:默认值为"transparent",用于指定包含行结束符\n的字符串如何被写入,不常用。

常见的MIME类型

类型描述典型事例
text表示文件是普通文本text/plain, text/html, text/css, text/javascript
image表示是图像文件,包括gif,但是不包含视频image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon
audio表示是音频文件audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav
video表示是视频文件video/webm, video/mp4
application表示文二进制数据application/octet-stream, application/pkcs12, application/vnd.mspowerpoint, application/xhtml+xml, application/xml, application/pdf

Blob属性和方法

通过造函数出来的对象拥有的属性方法:(2个属性4个方法)

javascript
let blob = new Blob(["A","B","c"],{type:'text/plain'})
let blob = new Blob(["A","B","c"],{type:'text/plain'})
  • blob.size:返回Blob对象中所包含数据的大小(字节)。
  • blob.tyoe:Blob对象所包含数据的MIME类型。如果类型未知,则该值为空字符串。
  • blob.stream():返回一个ReadableStream对象,读取后返回 Blob的数据。
  • blob.arrayBuffer():返回一个 Promise 对象,包含 blob 中的数据,并在 ArrayBuffer 中以二进制数据的形式呈现。
  • blob.text():方法返回一个 Promise 对象,包含 blob 中的内容,使用 UTF-8 格式编码。
  • blob.slice(start, end, contentType): 返回一个新的 Blob 对象,它包含了原始 Blob 对象的某一个段的数据。(用于切割文件,字节长度单位)。
    • start: 开始位置
    • end: 结束位置
    • contentType:切割后文件类型
ReadableStream拓展 (使用 stream() 函数与其返回的ReadableStream对象,你将得到一些有趣的能力:)
  • 调用方法getReader(),在返回的 stream 上获取一个对象,通过ReadableStreamDefaultReader接口提供的read()方法读取 blob 对象的方法。
  • 调用返回 stream 对象的pipeTo()方法将 blob 对象的数据传输到可写流。
  • 调用返回 stream 对象的pipeThrough()方法,通过一个TransformStream对象或其它任意可读可写对传输流对象。
  • 调用返回 stream 对象的tee()方法以准备可读流。该方法会返回一个数组,该数组包含两个新的 ReadableStream 对象,每个对象都会返回 Blob的内容。

File

File 对象是特殊类型的 Blob,且可以用在任意的 Blob 类型的 context 中。Blob 的属性和方法都可以用于 File 对象。

注意:File 对象中只存在于浏览器环境中,在 Node.js 环境中不存在。

在 JavaScript 中,主要有两种方法来获取 File 对象:

input

<input type="file" id="fileInput" multiple="multiple">

  • type="file":指定 input 的输入类型为文件。
  • id="fileInput":指定 input 的唯一 id。
  • multiple="multiple":指定 input 可以同时上传多个文件。
javascript
const fileInput = document.getElementById("fileInput");
fileInput.onchange = (e) => {
    console.log(e.target.files);
}
const fileInput = document.getElementById("fileInput");
fileInput.onchange = (e) => {
    console.log(e.target.files);
}

每个 File 对象都包含文件的一些属性,这些属性都继承自 Blob 对象:

  • lastModified:引用文件最后修改日期,为自1970年1月1日0:00以来的毫秒数;
  • lastModifiedDate:引用文件的最后修改日期;
  • name:引用文件的文件名;
  • size:引用文件的文件大小;
  • type:文件的媒体类型(MIME);
  • webkitRelativePath:文件的路径或 URL。 可以通过对比 size 属性来限制文件大小,通过对比 type 来限制上传文件的格式等。

文件拖拽

html
<div id="dragBox"></div>
<div id="dragBox"></div>
javascript
const dragBox = document.getElementById("dragBox");
dragBox.ondragover = (e) => {
    e.preventDefault();//阻止默认事件
}
dragBox.ondrop = (e) => {
    e.preventDefault();//阻止默认事件
    const files = e.dataTransfer.files;
    console.log(files)
}
const dragBox = document.getElementById("dragBox");
dragBox.ondragover = (e) => {
    e.preventDefault();//阻止默认事件
}
dragBox.ondrop = (e) => {
    e.preventDefault();//阻止默认事件
    const files = e.dataTransfer.files;
    console.log(files)
}

FileReader

FileReader 是一个异步 API,用于读取文件并提取其内容以供进一步使用。FileReader 可以将 Blob 读取为不同的格式。

注意:FileReader 仅用于以安全的方式从用户(远程)系统读取文件内容,不能用于从文件系统中按路径名简单地读取文件。

用 FileReader 构造函数来创建一个 FileReader 对象:

javascript
const reader = new FileReader();
const reader = new FileReader();

FileReader属性

  • error:表示在读取文件时发生的错误;
  • result:文件内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作。
  • readyState:表示FileReader状态的数字。取值如下:
    常量名描述
    EMPTY0还没有加载任何数据。
    LOADING1数据正在被加载。
    DONE2已完成全部的读取请求。

FileReader方法

  • FileReader.abort():该方法可以取消 FileReader 的读取操作,触发之后 readyState 为已完成(DONE)。
  • FileReader.readAsArrayBuffer(blob)读取指定的 Blob 或 File 的对象。当读取操作完成时,readyState 变成 DONE(已完成),并触发 loadend 事件,同时 result 属性将包含一个 ArrayBuffer 对象以表示所读取文件的数据
  • FileReader.readAsDataURL(blob)读取指定的 Blob 或 File 的对象。当读取操作完成时,readyState 变成 DONE(已完成),并触发 loadend 事件,同时 result 属性将包含一个data:URL 格式的字符串(base64 编码)以表示所读取文件的内容
  • FileReader.readAsText(blob,encoding)读取指定的 Blob 或 File 的对象。当读取操作完成时,readyState 变成 DONE(已完成),并触发 loadend 事件,同时 result 属性将包含一个文本字符串的形式包含文件的内容。(不适用于大文件,对于大型文件,首选readAsArrayBuffer(blob))
    • 第一个参数:Blob类型 或 File类型
    • 第二个参数:编码类型 (可选),传入一个字符串类型的编码类型,如缺省,则默认为“utf-8”类型。
  • FileReader.readAsBinaryString(blob) 非标准:读取指定的 Blob 或 File 对象,当读取完成的时候,readyState 会变成DONE(已完成),并触发 loadend 事件,同时 result 属性将包含所读取文件原始二进制格式。

FileReader事件

  • loadstart:当文件读取操作开始时,将触发。
  • abort:该事件在读取操作被中断时触发。
  • error:该事件在读取操作发生错误时触发。
  • load:该事件在读取操作完成时触发。
  • loadend: 无论文件读取是否成功完成,都会触发。
  • progress:该事件在读取 Blob 时触发。

progress 事件提供了两个属性:loaded(已读取量)和total(需读取总量)。

javascript
const reader = new FileReader();

function addListeners(reader) {
    reader.addEventListener('loadstart', handleEvent);
    reader.addEventListener('load', handleEvent);
    reader.addEventListener('loadend', handleEvent);
    reader.addEventListener('progress', handleEvent);
    reader.addEventListener('error', handleEvent);
    reader.addEventListener('abort', handleEvent);
}

function handleEvent(e) {
    console.log(`${e.type}: ${e.loaded}`)
    if (e.type === "load") {
        console.log(reader.result)
    }
    if (e.type === "progress" && e.loaded && e.total) {
        const percent = (e.loaded / e.total) * 100;
        console.log(`上传进度: ${Math.round(percent)} %`);
    }
}

fileInput.onchange = (e) => {
    let file = e.target.files[0]
    if (file) {
        reader.readAsDataURL(file)
        addListeners(reader)
    }
}
const reader = new FileReader();

function addListeners(reader) {
    reader.addEventListener('loadstart', handleEvent);
    reader.addEventListener('load', handleEvent);
    reader.addEventListener('loadend', handleEvent);
    reader.addEventListener('progress', handleEvent);
    reader.addEventListener('error', handleEvent);
    reader.addEventListener('abort', handleEvent);
}

function handleEvent(e) {
    console.log(`${e.type}: ${e.loaded}`)
    if (e.type === "load") {
        console.log(reader.result)
    }
    if (e.type === "progress" && e.loaded && e.total) {
        const percent = (e.loaded / e.total) * 100;
        console.log(`上传进度: ${Math.round(percent)} %`);
    }
}

fileInput.onchange = (e) => {
    let file = e.target.files[0]
    if (file) {
        reader.readAsDataURL(file)
        addListeners(reader)
    }
}

ArrayBuffer

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 的内容不能直接操作,只能通过 DataView 对象或 TypedArrray 对象来访问。这些对象用于读取和写入缓冲区内容。

ArrayBuffer构造函数

new ArrayBuffer(bytelength)

  • 返回:返回一个新的指定大小的ArrayBuffer对象,内容初始化为0。
  • 参数:它接受一个参数,即 bytelength,表示要创建数组缓冲区的大小(以字节为单位。);

ArrayBuffer属性

  • ArrayBuffer.prototype.byteLength:它是一个只读属性,表示 ArrayBuffer 的 byte 的大小,在 ArrayBuffer 构造完成时生成,不可改变。

ArrayBuffer方法

  • ArrayBuffer.prototype.slice():用来截取 ArrayBuffer 实例,它返回一个新的 ArrayBuffer。它的内容是这个 ArrayBuffer 的字节副本,从 begin(包括),到 end(不包括)
  • ArrayBuffer.isView():返回值是一个布尔值。如果参数是 ArrayBuffer 的视图实例则返回 true,否则返回 false。这个方法就是用来判断参数是否是 TypedArray 实例或者 DataView 实例
javascript
ArrayBuffer.isView([]);                  // false
ArrayBuffer.isView({});                  // false
rayBuffer.isView(new ArrayBuffer(10));   // false
ArrayBuffer.isView(new Uint8Array());    // true
ArrayBuffer.isView(new Float32Array());  // true

const buffer = new ArrayBuffer(2);
const dv = new DataView(buffer);
ArrayBuffer.isView(dv);                  // true
ArrayBuffer.isView([]);                  // false
ArrayBuffer.isView({});                  // false
rayBuffer.isView(new ArrayBuffer(10));   // false
ArrayBuffer.isView(new Uint8Array());    // true
ArrayBuffer.isView(new Float32Array());  // true

const buffer = new ArrayBuffer(2);
const dv = new DataView(buffer);
ArrayBuffer.isView(dv);                  // true

TypedArray、DataView

ArrayBuffer 本身就是一个黑盒,不能直接读写所存储的数据,需要借助以下视图对象来读写:

  • TypedArray:用来生成内存的视图,通过9个构造函数,可以生成9种数据格式的视图。

  • DataViews:用来生成内存的视图,可以自定义格式和字节序。

图片

TypedArray视图 vs DataView视图
两者区别主要是字节序,前者的数组成员都是同一个数据类型,后者的数组成员可以是不同的数据类型。(类似TS中数组和元组)

ArrayBuffer 与 Blob
Blob 作为一个整体文件,适合用于传输;当需要对二进制数据进行操作时(比如要修改某一段数据时),就可以使用 ArrayBuffer。

TypedArray

TypedArray 对象一共提供 9 种类型的视图

元素类型化数组字节描述
Int8Int8Array18 位 符号整数
Uint8Uint8Array18 位 符号整数
Uint8CUint8ClampedArray18 位 符号整数
Int16Int16Array216 位 符号整数
Uint16Uint16Array216 位 符号整数
Int32Int32Array432 位 符号整数
Uint32Uint32Array432 位 符号整数
Float32Float32Array432 位浮点
Float64Float64Array864 位浮点

Uint8Array: 将 ArrayBuffer 中的每个字节视为一个整数,可能的值从 0 到 255 (一个字节等于 8 位)。 这样的值称为“8 位无符号整数”。

Uint16Array:将 ArrayBuffer 中任意两个字节视为一个整数,可能的值从 0 到 65535。 这样的值称为“16 位无符号整数”。

Uint32Array:将 ArrayBuffer 中任何四个字节视为一个整数,可能值从 0 到 4294967295,这样的值称为“32 位无符号整数”。

这些构造函数生成的对象统称为 TypedArray 对象。它们和正常的数组很类似,都有length 属性,都能用索引获取数组元素,所有数组的方法都可以在类型化数组上面使用。

类型化数组和数组有什么区别:

  • 类型化数组的元素都是连续的,不会为空;
  • 类型化数组的所有成员的类型和格式相同;
  • 类型化数组元素默认值为 0;
  • 类型化数组本质上只是一个视图层,不会存储数据,数据都存储在更底层的 ArrayBuffer 对象中。

TypedArray属性方法

TypedArray 的语法如下(TypedArray只是一个概念,实际使用的是那9个对象):

  • new TypedArray(length):通过分配指定长度内容进行分配。
  • new TypedArray(typedArray):接收一个视图实例作为参数。
  • new TypedArray(object):参数可以是一个普通数组。
  • new TypedArray(buffer, byteOffset, length)
    • buffer:一个ArrayBuffer对象。
    • byteOffset(可选):视图开始的字节序号,默认从0开始。
    • length:视图包含的数据个数,默认直到本段内存区域结束。

BYTES_PER_ELEMENT

每种视图的构造函数都有一个 BYTES_PER_ELEMENT 属性,表示这种数据类型占据的字节数:

javascript
Int8Array.BYTES_PER_ELEMENT // 1
Uint8Array.BYTES_PER_ELEMENT // 1
Int16Array.BYTES_PER_ELEMENT // 2
Uint16Array.BYTES_PER_ELEMENT // 2
Int32Array.BYTES_PER_ELEMENT // 4
Uint32Array.BYTES_PER_ELEMENT // 4
Float32Array.BYTES_PER_ELEMENT // 4
Float64Array.BYTES_PER_ELEMENT // 8
Int8Array.BYTES_PER_ELEMENT // 1
Uint8Array.BYTES_PER_ELEMENT // 1
Int16Array.BYTES_PER_ELEMENT // 2
Uint16Array.BYTES_PER_ELEMENT // 2
Int32Array.BYTES_PER_ELEMENT // 4
Uint32Array.BYTES_PER_ELEMENT // 4
Float32Array.BYTES_PER_ELEMENT // 4
Float64Array.BYTES_PER_ELEMENT // 8

BYTES_PER_ELEMENT 属性也可以在类型化数组的实例上获取:

javascript
const buffer = new ArrayBuffer(16); 
const view = new Uint32Array(buffer); 
console.log(Uint32Array.BYTES_PER_ELEMENT); // 4
const buffer = new ArrayBuffer(16); 
const view = new Uint32Array(buffer); 
console.log(Uint32Array.BYTES_PER_ELEMENT); // 4

TypedArray.prototype.buffer TypedArray 实例的 buffer 属性会返回内存中对应的 ArrayBuffer对象,只读属性。

TypedArray.prototype.slice() TypeArray 实例的 slice方法可以返回一个指定位置的新的 TypedArray实例。

TypedArray.byteLength:TypedArray 占据的内存长度,单位为字节。

TypedArray.length:ypedArray 元素个数。

DataView

DataView 视图是一个可以从 二进制 ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。

DataView视图提供更多操作选项,而且支持设定字节序。本来,在设计目的上,ArrayBuffer对象的各种TypedArray视图,是用来向网卡、声卡之类的本机设备传送数据,所以使用本机的字节序就可以了;而DataView视图的设计目的,是用来处理网络设备传来的数据,所以大端字节序或小端字节序是可以自行设定的。

new DataView(buffer,byteOffset,byteLength):

  • buffer:一个已经存在的 ArrayBuffer 对象,DataView 对象的数据源。
  • byteOffset:可选,此 DataView 对象的第一个字节在 buffer 中的字节偏移。如果未指定,则默认从第一个字节开始。
  • byteLength:可选,此 DataView 对象的字节长度。如果未指定,这个视图的长度将匹配 buffer 的长度。

DataView实例下常用属性:

buffer:返回对应的ArrayBuffer对象;

byteLength:返回占据的内存字节长度;

byteOffset:返回当前视图从对应的ArrayBuffer对象的哪个字节开始。

javascript
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.buffer;     // ArrayBuffer对象
view.byteLength; // 16
view.byteOffset; // 0
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);
view.buffer;     // ArrayBuffer对象
view.byteLength; // 16
view.byteOffset; // 0

DataView读取内存: DataView 实例提供了以下方法来读取内存,它们的参数都是一个字节序号,表示开始读取的字节位置。

getInt8:读取1个字节,返回一个8位整数。
getUint8:读取1个字节,返回一个无符号的8位整数。
getInt16:读取2个字节,返回一个16位整数。
getUint16:读取2个字节,返回一个无符号的16位整数。
getInt32:读取4个字节,返回一个32位整数。
getUint32:读取4个字节,返回一个无符号的32位整数。
getFloat32:读取4个字节,返回一个32位浮点数。
getFloat64:读取8个字节,返回一个64位浮点数。
getInt8:读取1个字节,返回一个8位整数。
getUint8:读取1个字节,返回一个无符号的8位整数。
getInt16:读取2个字节,返回一个16位整数。
getUint16:读取2个字节,返回一个无符号的16位整数。
getInt32:读取4个字节,返回一个32位整数。
getUint32:读取4个字节,返回一个无符号的32位整数。
getFloat32:读取4个字节,返回一个32位浮点数。
getFloat64:读取8个字节,返回一个64位浮点数。
javascript
const buffer = new ArrayBuffer(24);
const view = new DataView(buffer);

// 从第1个字节读取一个8位无符号整数
const view1 = view.getUint8(0);

// 从第2个字节读取一个16位无符号整数
const view2 = view.getUint16(1);

// 从第4个字节读取一个16位无符号整数
const view3 = view.getUint16(3);
const buffer = new ArrayBuffer(24);
const view = new DataView(buffer);

// 从第1个字节读取一个8位无符号整数
const view1 = view.getUint8(0);

// 从第2个字节读取一个16位无符号整数
const view2 = view.getUint16(1);

// 从第4个字节读取一个16位无符号整数
const view3 = view.getUint16(3);

DataView写入内存: DataView 实例提供了以下方法来写入内存,它们都接受两个参数,第一个参数表示开始写入数据的字节序号,第二个参数为写入的数据。

setInt8:写入1个字节的8位整数。
setUint8:写入1个字节的8位无符号整数。
setInt16:写入2个字节的16位整数。
setUint16:写入2个字节的16位无符号整数。
setInt32:写入4个字节的32位整数。
setUint32:写入4个字节的32位无符号整数。
setFloat32:写入4个字节的32位浮点数。
setFloat64:写入8个字节的64位浮点数。
setInt8:写入1个字节的8位整数。
setUint8:写入1个字节的8位无符号整数。
setInt16:写入2个字节的16位整数。
setUint16:写入2个字节的16位无符号整数。
setInt32:写入4个字节的32位整数。
setUint32:写入4个字节的32位无符号整数。
setFloat32:写入4个字节的32位浮点数。
setFloat64:写入8个字节的64位浮点数。

Object URL

Object URL(MDN定义名称)又称Blob URL(W3C定义名称),是HTML5中的新标准。它是一个用来表示File Object 或Blob Object 的URL。

其实 Blob URL/Object URL 是一种伪协议,允许将 Blob 和 File 对象用作图像、二进制数据下载链接等的 URL 源。

对于 Blob/File 对象,可以使用 URL构造函数的 createObjectURL() 方法创建将给出的对象的 URL。这个 URL 对象表示指定的 File 对象或 Blob 对象。我们可以在 img、script 标签中或者 a 和 link 标签的 href 属性中使用这个 URL。

javascript
<input type="file" id="fileInput" />
<img id="preview" />

const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");

fileInput.onchange = (e) => {
  preview.src = URL.createObjectURL(e.target.files[0]);
  console.log(preview.src);
};
<input type="file" id="fileInput" />
<img id="preview" />

const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");

fileInput.onchange = (e) => {
  preview.src = URL.createObjectURL(e.target.files[0]);
  console.log(preview.src);
};

createObjectURL() 可以将Blob/File对象转化为URL,通过这个URL 就可以实现文件下载或者图片显示等。

当我们使用createObjectURL()方法创建一个data URL 时,就需要使用revokeObjectURL()方法从内存中清除它来释放内存。虽然浏览器会在文档卸载时自动释放 Data URL,但为了提高性能,我们应该使用createObjectURL()来手动释放它。revokeObjectURL()方法接受一个Data URL 作为其参数,返回undefined。

javascript
const objUrl = URL.createObjectURL(new File([""], "filename"));
console.log(objUrl);
URL.revokeObjectURL(objUrl);
const objUrl = URL.createObjectURL(new File([""], "filename"));
console.log(objUrl);
URL.revokeObjectURL(objUrl);

Base64

Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。Base64 编码普遍应用于需要通过被设计为处理文本数据的媒介上储存和传输二进制数据而需要编码该二进制数据的场景。这样是为了保证数据的完整并且不用在传输过程中修改这些数据。

在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:

  • atob():解码,解码一个 Base64 字符串;
  • btoa():编码,从一个字符串或者二进制数据编码一个 Base64 字符串。
javascript
btoa("JavaScript")       // 'SmF2YVNjcmlwdA=='
atob('SmF2YVNjcmlwdA==') // 'JavaScript'
btoa("JavaScript")       // 'SmF2YVNjcmlwdA=='
atob('SmF2YVNjcmlwdA==') // 'JavaScript'

base64 的实际应用场景

  1. 其实多数场景就是基于Data URL。比如,使用toDataURL()方法把 canvas 画布内容生成 base64 编码格式的图片:
javascript
const canvas = document.getElementById('canvas'); 
const ctx = canvas.getContext("2d");
const dataUrl = canvas.toDataURL();
const canvas = document.getElementById('canvas'); 
const ctx = canvas.getContext("2d");
const dataUrl = canvas.toDataURL();
  1. 使用readAsDataURL()方法把上传的文件转为base64格式的data URI。比如上传头像展示或者编辑:
javascript
<input type="file" id="fileInput" />
<img id="preview" />

const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");
const reader = new FileReader();

fileInput.onchange = (e) => {
  reader.readAsDataURL(e.target.files[0]);
};

reader.onload = (e) => {
  preview.src = e.target.result;
  console.log(e.target.result);
};
<input type="file" id="fileInput" />
<img id="preview" />

const fileInput = document.getElementById("fileInput");
const preview = document.getElementById("preview");
const reader = new FileReader();

fileInput.onchange = (e) => {
  reader.readAsDataURL(e.target.files[0]);
};

reader.onload = (e) => {
  preview.src = e.target.result;
  console.log(e.target.result);
};

将图片(二进制数据)转化为可打印的字符,也便于数据的传输。

另外,一些小的图片都可以使用 base64 格式进行展示,img标签和background的 url 属性都支持使用base64 格式的图片,这样做也可以减少 HTTP 请求。

格式转换

ArrayBuffer → blob

javascript
const blob = new Blob([new Uint8Array(buffer, byteOffset, length)]);
const blob = new Blob([new Uint8Array(buffer, byteOffset, length)]);

ArrayBuffer → base64

javascript
const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));
const base64 = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

base64 → blob

javascript
const base64toBlob = (base64Data, contentType, sliceSize) => {
  const byteCharacters = atob(base64Data);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, {type: contentType});
  return blob;
}
const base64toBlob = (base64Data, contentType, sliceSize) => {
  const byteCharacters = atob(base64Data);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    const slice = byteCharacters.slice(offset, offset + sliceSize);

    const byteNumbers = new Array(slice.length);
    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  const blob = new Blob(byteArrays, {type: contentType});
  return blob;
}

blob → ArrayBuffer

javascript
function blobToArrayBuffer(blob) { 
  return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject;
      reader.readAsArrayBuffer(blob);
  });
}
function blobToArrayBuffer(blob) { 
  return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.onload = () => resolve(reader.result);
      reader.onerror = () => reject;
      reader.readAsArrayBuffer(blob);
  });
}

blob → base64

javascript
function blobToBase64(blob) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
    reader.readAsDataURL(blob);
  });
}
function blobToBase64(blob) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
    reader.readAsDataURL(blob);
  });
}

blob → Object URL

javascript
const objectUrl = URL.createObjectURL(blob);
const objectUrl = URL.createObjectURL(blob);