web二进制(string ----> Blob -----> (ArrayBuffer DataURLObjectURLText)相互转换)

Posted 胖鹅68

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web二进制(string ----> Blob -----> (ArrayBuffer DataURLObjectURLText)相互转换)相关的知识,希望对你有一定的参考价值。

文章目录

一、文章参考

  1. 玩转前端二进制

二、常见对象

2.1 存放数据的容器:ArrayBuffer(字节)

2.1.1 概念

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。

它是一个字节数组,通常在其他语言中称为“byte array”。

你不能直接操作 ArrayBuffer 的内容,而是要通过 TypedArray 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

2.1.2 构造函数 new ArrayBuffer(length)

  • 参数 length
    • 要创建的 ArrayBuffer 的大小,单位为字节。
  • 返回值
    • 一个指定大小的 ArrayBuffer 对象,其内容被初始化为 0

2.1.3 操作二进制数据的工具:DataView& TypedArray

Arraybuffer 中的内容是不能直接操作的,需要通过 TypedArray 和 DataView 对象来操作

2.1.3.1 TypedArray

  • 概念

    • TypedArray 是一个接口,js 中是没有名为 TypedArray 的对象的
    • 对象描述了描述了一个底层的二进制数据缓冲区(binary data buffer)的一个类数组视图(view)
  • 实现函数

函数名解释
new Int8Array();
new Uint8Array();
new Uint8ClampedArray();
new Int16Array();
new Uint16Array();
new Int32Array();
new Uint32Array();
new Float32Array();
new Float64Array();
  • 个人理解
    • ArrayBuffer定义的是一个字节(8bit)
    • TypedArray的实现函数则是对ArrayBuffer中的二进制的bit位做如何解析
      • 比如解析1个字节,则是8bit, 使用Int8Array
      • 比如解析2个字节,则是16bit,使用 Int16Array

2.1.3.2 DataView 读写多种数值类型

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

  • 构造函数 DataView(buffer [, byteOffset [, byteLength]])

    • 参数 buffer
      • 一个 已经存在的ArrayBuffer 或 SharedArrayBuffer 对象,DataView 对象的数据源。
    • byteOffset 可选
      • 此 DataView 对象的第一个字节在 buffer 中的字节偏移。如果未指定,则默认从第一个字节开始。
    • byteLength 可选
      • 此 DataView 对象的字节长度。如果未指定,这个视图的长度将匹配buffer的长度。
    • 返回值
      • 一个表示指定数据缓存区的新DataView 对象。(这句话也许不是非常有助于说明清楚)
      • 可以把返回的对象想象成一个二进制字节缓存区 array buffer 的“解释器”——它知道如何在读取或写入时正确地转换字节码。这意味着它能在二进制层面处理整数与浮点转化、字节顺序等其他有关的细节问题。

读 函数

函数说明
DataView.prototype.getInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个8-bit数(一个字节).
DataView.prototype.getUint8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个8-bit数(无符号字节).
DataView.prototype.getInt16()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个16-bit数(短整型).
DataView.prototype.getUint16()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个16-bit数(无符号短整型).
DataView.prototype.getInt32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个32-bit数(长整型).
DataView.prototype.getUint32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个32-bit数(无符号长整型).
DataView.prototype.getFloat32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个32-bit数(浮点型).
DataView.prototype.getFloat64()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处获取一个64-bit数(双精度浮点型).

写 函数

函数说明
DataView.prototype.setInt8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个8-bit数(一个字节).
DataView.prototype.setUint8()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个8-bit数(无符号字节).
DataView.prototype.setInt16()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个16-bit数(短整型).
DataView.prototype.setUint16()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个16-bit数(无符号短整型).
DataView.prototype.setInt32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个32-bit数(长整型).
DataView.prototype.setUint32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个32-bit数(无符号长整型).
DataView.prototype.setFloat32()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个32-bit数(浮点型).
DataView.prototype.setFloat64()从DataView起始位置以byte为计数的指定偏移量(byteOffset)处储存一个64-bit数(双精度浮点型).

2.1.4 案例

  1. TypedArray 相同内存不同类型读取结果不一致
'use strict';
// ArrayBuffer 不能直接操作,需要 DataView或者 TypeArray
const buffer = new ArrayBuffer(8);
// 8个字节的ArrayBuffer, 8 * 8 = 64 个bit位
console.log(buffer.byteLength); // 8

const int8Array = new Int8Array(buffer);
// 元素长度 1 个字节,占用 8 位
console.log(int8Array.length);

const int16Array = new Int16Array(buffer);
// 元素长度 2 个字节,占用 4 位
console.log(int16Array.length); // 4
  1. DataView 自由读取多种数值类型
'use strict';
// ArrayBuffer 不能直接操作,需要 DataView或者 TypeArray
// 创建2 个字节的ArrayBuffer
const buffer = new ArrayBuffer(2);

console.log(buffer.byteLength);

const dataView = new DataView(buffer);
dataView.setInt8(0, 1); // 设置第一个字节 为1,即 00000001 (二进制)
dataView.setInt8(1, 2); // 设置第二个字节 为2,即 00000010 (二进制)

console.log(dataView.getInt8(0)); // 1, asscii 码值
console.log(dataView.getInt8(1)); // 2, asscii 码值

// 去两个字节的值 258
// 00000001 00000010 (二进制)
console.log(dataView.getInt16(0));

// DataView 和 TypeArray 内部引用了buffer
console.log(dataView.buffer === buffer);
  1. UTF8转Base64(编码转换)
'use strict';
const  Buffer  = require('buffer');

// 默认是 UTF8 编码
console.log(new Buffer.from('黄彪').toString('base64')); // 6buE5b2q

console.log(new Buffer.from('6buE5b2q', 'base64').toString()); // 黄彪

2.2 Blob

2.2.1 概念

Blob 对象表示一个不可变、原始数据的类文件对象。
Blob 表示的不一定是javascript原生格式的数据
Blob是用来支持文件操作的

2.2.2 构造函数 Blob( array, options )

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

2.2.3 属性

  • Blob.size 只读
    Blob 对象中所包含数据的大小(字节)。
  • Blob.type 只读
    一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。

2.2.4 方法

  • Blob.slice([start[, end[, contentType]]])
    返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据。
  • Blob.stream()
    返回一个能读取blob内容的 ReadableStream。
  • Blob.text()
    • 功能: 返回一个promise且包含blob所有内容的UTF-8格式的 USVString。
    • 语法
var textPromise = blob.text();
blob.text().then(text => /* 执行的操作…… */);
var text = await blob.text();
  • Blob.arrayBuffer()
    返回一个promise且包含blob所有内容的二进制格式的 ArrayBuffer

与 FileReader 的 readAsText() 的区别

Blob.text() 返回的是一个 promise 对象,而 FileReader.readAsText() 是一个基于事件的 API。
Blob.text() 总是使用 UTF-8 进行编码,而 FileReader.readAsText() 可以使用不同编码方式,取决于 blob 的类型和一个指定的编码名称。

2.2.5 应用场景

  1. 文件下载

通过URL.createObjectURL(blob)生成的Blob URL,赋值给a.download属性

  1. 图片展示

通过URL.createObjectURL(blob)生成的Blob URL,赋值给img.src属性

  1. 分片上传

通过blob.slice可以分割二进制数据为子Blob上传

  1. 本地读取文件

Filereader的API可以将Blob或File转化为文件ArrayBuffer/DataURL

2.3 FileReader

2.3.1 概念

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

2.3.2 构造方法 new FileReader()

没有参数

2.3.3 属性

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

2.3.4 事件处理

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

2.3.5 方法

函数名说明参数返回值
FileReader.abort()中止读取操作。在返回时,readyState属性为DONE。
FileReader.readAsArrayBuffer()开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.result 属性中将包含一个 ArrayBuffer 对象以表示所读取文件的数据
FileReader.readAsBinaryString()开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。
FileReader.readAsDataURL(blob)开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。Blob类型 或 File类型result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容
FileReader.readAsText(blob[, encoding])开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。这个方法是异步的,也就是说,只有当执行完成后才能够查看到结果,如果直接查看是无结果的,并返回undefinedblob Blob类型 或 File类型;encoding传入一个字符串类型的编码类型,如缺省,则默认为“utf-8”类型

2.3.6 案例

  1. 预览选中的图片
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="file" onchange="previewFile()">
    <img src="" alt="">
  </body>
  <script>
    function previewFile() 
      var preview = document.querySelector("img");
      var file = document.querySelector("input[type=file]").files[0];
      var reader = new FileReader();

      reader.addEventListener("load",
        function() 
          console.log(arguments)
          debugger
          preview.src = reader.result;
        ,
        false
      );

      if (file) 
        reader.readAsDataURL(file);
      
    
  </script>
</html>
  1. 读取本地txt文件
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <input type="file" id='upload' />
</body>
<script>
  
document.getElementById('upload').addEventListener('change', function (e) 
    var file = this.files[0];
    const reader = new FileReader();
    reader.onload = function () 
        const result = reader.result;
        debugger
        console.log(result);
    
    reader.readAsText(file);
, false);

</script>
</html>
  1. Blob串转 ArrayBuffer、String、DataURL、ObjectURL
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
  <script>
    const jsonData =  name: "huangbiao", age: 32 ;
    let jsonStr = JSON.stringify(jsonData);
    console.log(jsonStr);
    // 字符串 转为 Blob 对象
    let blob = new Blob([jsonStr],  type: "application/json" );
    console.log("blob.size", blob.size);

    function readBlob(blob, type) 
      return new Promise(function (resolve) 
        let reader = new FileReader();
        reader.onload = function (event) 
          console.log(event);
          resolve(event.target.result);
        ;
        switch (type) 
          case "ArrayBuffer":
            // FileReader 将 Blob 转为 ArrayBuffer 对象(即Buffer对象)
            reader.readAsArrayBuffer(blob);
            break;
          case "DataURL":
            // FileReader 将 Blob 转为 Base64字符串
            reader.readAsDataURL(blob);
            break;
          case "Text":
            // FileReader 将 Blob 转为 文本,并且是以UTF8编码的形式
            reader.readAsText(blob, "utf-8");
            break;
          case "ObjectURL":
            // FileReader 将 Blob 转为 ObjectURL对象(一个路径指向文件)
            const objectURL = URL.createObjectURL(blob)
            resolve(objectURL);
            break;
          default:
            break;
        
      );
    

    readBlob(blob ,'ArrayBuffer').then(result => 
      console.log('ArrayBuffer',result);
    )
    readBlob(blob ,'DataURL').then(result => 
      console.log('DataURL',result);
    )
    readBlob(blob ,'Text').then(result => 
      console.log('Text',result);
    )
    readBlob(blob ,'ObjectURL').then(result => 
      console.log('ObjectURL',result);
    )
  </script>
</html>

2.4 File

2.4.1 概念

  • File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
  • File对象可以看作一种特殊的Blob对象

2.4.2 来源

  • File 对象是来自用户在一个 元素上选择文件后返回的 FileList 对象
  • 也可以是来自由拖放操作生成的 DataTransfer 对象
  • 或者来自 HTMLCanvasElement 上的 mozGetAsFile() API

2.4.3 构造函数 new File(bits, name[, options]);

  • bits
    一个包含ArrayBuffer,ArrayBufferView,Blob,或者 DOMString 对象的 Array — 或者任何这些对象的组合。这是 UTF-8 编码的文件内容。
  • name
    USVString,表示文件名称,或者文件路径。
  • options 可选
    选项对象,包含文件的可选属性
    type: DOMString,表示将要放到文件中的内容的 MIME 类型。默认值为 “” 。
    lastModified: 数值,表示文件最后修改时间的 Unix 时间戳(毫秒)。默认值为 Date.now()。
var file = new File(["foo"], "foo.txt", 
  type: "text/plain",
);

2.4.4 属性

File 接口也继承了 Blob 接口的属性:

属性名是否只读说明
File.lastModified只读返回当前 File 对象所引用文件最后修改时间,自 UNIX 时间起始值(1970年1月1日 00:00:00 UTC)以来的毫秒数。
File.lastModifiedDate只读返回当前 File 对象所引用文件最后修改时间的 Date 对象。
File.name只读返回当前 File 对象所引用文件的名字。
File.size只读返回文件的大小。
File.webkitRelativePath只读返回 File 相关的 path 或 URL。
File.type只读返回文件的 多用途互联网邮件扩展类型(MIME Type)

2.5 DataURL

2.5.1 FileReader.readAsDataURL(blob);

包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

2.5.1个人理解

就是base64的字符串编码,前面的“data:”格式固定

2.5.1数据案例

data:application/json;base64,eyJuYW1lIjoiaHVhbmdiaWFvIiwiYWdlIjozMn0=

2.5.1Base64

  • atob() 解码
    • a 代表 ASCII,而 b 代表 Blob,即二进制
    • 表示 ASCII 到二进制
    • 对应的是解码操作
  • btoa() 编码
    • a 代表 ASCII,而 b 代表 Blob,即二进制
    • 二进制到 ASCII
    • 对应的是编码操作

2.6 ObjectURL

2.6.1 URL.createObjectURL() 静态方法

  • 语法
    objectURL = URL.createObjectURL(object);
  • 参数 object
    用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。​
  • 返回值 objectURL
    一个DOMString包含了一个对象URL,该URL可用于指定源 object的内容。
    这个新的URL 对象表示指定的 File 对象或 Blob 对象。
    个人理解:一个类似于URL的地址,代表一个File对象(文件) 或则 Blob 对象(数据在内存中)

2.6.1 URL

参考 URL MDN

2.6.2.1 概念

URL接口用于解析,构造,规范化和编码 URLs。
个人理解:按照规范方便解析URL地址,通过方法获取对应的属性(例如地址、端口、协议、参数等),而不是人为的去解析字符串

2.6.2.2 构造函数 new URL(url, [base])

url
是一个表示绝对或相对 URL 的 DOMString。如果url 是相对 URL,则会将 base 用作基准 URL。如果 url 是绝对URL,则将忽略 base,无论是否有给出。
base 可选
是一个表示基准 URL 的 DOMString,在 url 是相对 URL 时,它才会起效。如果未指定,则默认为 ‘’。

2.6.2.3 属性

属性说明
hash包含’#'的USVString,后跟URL的片段标识符。
host一个USVString,其中包含域(即主机名),后跟(如果指定了端口)“:”和URL的端口。
hostname包含 URL 域名的 USVString。
href包含完整 URL 的 USVString。
origin 只读返回一个包含协议名、域名和端口号的 USVString。
password包含在域名前面指定的密码的 USVString 。
pathname以 ‘/’ 起头紧跟着 URL 文件路径的 DOMString。
port包含 URL 端口号的 USVString。
protocol包含 URL 协议名的 USVString,末尾带 ‘:’。
search一个USVString ,指示URL的参数字符串; 如果提供了任何参数,则此字符串包括所有参数,并以开头的“?”开头 字符。
searchParams 只读URLSearchParams对象,可用于访问search中找到的各个查询参数。
username包含在域名前面指定的用户名的 USVString。

2.6.2.4 方法

方法名说明
toString()返回包含整个URL的USVString。 它是URL.href的同义词,尽管它不能用于修改值。
toJSON()返回包含整个URL的USVString。 它返回与href属性相同的字符串。

2.6.2.5 静态方法

方法名参数说明
URL.createObjectURL(object);用于创建 URL 的 File 对象、Blob 对象或者 MediaSource 对象。​返回一个DOMString ,包含一个唯一的blob链接(该链接协议为以blob:,后跟唯一标识浏览器中的对象的掩码)。
revokeObjectURL()销毁之前使用URL.createObjectURL()方法创建的URL实例。

createObjectURL 内存管理
在每次调用 createObjectURL() 方法时,都会创建一个新的 URL 对象,即使你已经用相同的对象作为参数创建过。当不再需要这些 URL 对象时,每个对象必须通过调用 URL.revokeObjectURL() 方法来释放
浏览器在 document 卸载的时候,会自动释放它们,但是为了获得最佳性能和内存使用状况,你应该在安全的时机主动释放掉它们。

2.6.2.6 字符串转为Blob对象实现文件下载(因为Blob可以转为ObjectURL)

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset`web_sys::Url::create_object_url_with_blob(&blob)` 未正确格式化二进制数据

Oracle35BLOB字段和CLOB字段

需要在 IE 窗口中打开 blob/PDF

ORACLE数据库BLOB如何转化类型

前端如何缓存blob文件之图片

使用 web2py 将 BLOB 保存到 MySQL