整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JS二進(jìn)制:Blob、File、FileReader、ArrayBuffer、Base64

          lob

          Blob 全稱為 binary large object ,即二進(jìn)制大對(duì)象,它是 JavaScript 中的一個(gè)對(duì)象,表示原始的類似文件的數(shù)據(jù)。實(shí)際上,Blob 對(duì)象是包含有只讀原始數(shù)據(jù)的類文件對(duì)象。簡(jiǎn)單來說,Blob 對(duì)象就是一個(gè)不可修改的二進(jìn)制文件。

          new Blob(array, options);

          array:由 ArrayBuffer、ArrayBufferView、Blob、DOMString 等對(duì)象構(gòu)成的,將會(huì)被放進(jìn) Blob options:可選的 BlobPropertyBag 字典,它可能會(huì)指定如下兩個(gè)屬性。 type:默認(rèn)值為 "",表示將會(huì)被放入到 blob 中的數(shù)組內(nèi)容的 MIME 類型。

          這里可以成為動(dòng)態(tài)文件創(chuàng)建,其正在創(chuàng)建一個(gè)類似文件的對(duì)象。這個(gè) blob 對(duì)象上有兩個(gè)屬性:

          size:Blob對(duì)象中所包含數(shù)據(jù)的大小(字節(jié))

          type:字符串,認(rèn)為該Blob對(duì)象所包含的 MIME 類型

          下面來看打印結(jié)果:

          const blob = new Blob(["Hello World"], {type: "text/plain"});
          
          console.log(blob.size); // 11
          console.log(blob.type); // "text/plain"
          復(fù)制代碼

          注意,字符串"Hello World"是 UTF-8 編碼的,因此它的每個(gè)字符占用 1 個(gè)字節(jié)。

          到現(xiàn)在,Blob 對(duì)象看起來似乎我們還是沒有啥用。那該如何使用 Blob 對(duì)象呢?可以使用 URL.createObjectURL() 方法將其轉(zhuǎn)化為一個(gè) URL,并在 Iframe 中加載:

          <iframe></iframe>
          
          const iframe = document.getElementsByTagName("iframe")[0];
          
          const blob = new Blob(["Hello World"], {type: "text/plain"});
          
          iframe.src = URL.createObjectURL(blob);

          Blob 分片

          其有三個(gè)參數(shù):

          start:設(shè)置切片的起點(diǎn),即切片開始位置。默認(rèn)值為 0,這意味著切片應(yīng)該從第一個(gè)字節(jié)開始

          end:設(shè)置切片的結(jié)束點(diǎn),會(huì)對(duì)該位置之前的數(shù)據(jù)進(jìn)行切片。默認(rèn)值為blob.size

          contentType:設(shè)置新 blob 的 MIME 類型。如果省略 type,則默認(rèn)為 blob 的原始值

          const iframe = document.getElementsByTagName("iframe")[0];
          
          const blob = new Blob(["Hello World"], {type: "text/plain"});
          
          const subBlob = blob.slice(0, 5);
          
          iframe.src = URL.createObjectURL(subBlob);
          復(fù)制代碼

          此時(shí)頁面會(huì)顯示"Hello"。

          File

          文件(File)接口提供有關(guān)文件的信息,并允許網(wǎng)頁中的 JavaScript 訪問其內(nèi)容。實(shí)際上,F(xiàn)ile 對(duì)象是特殊類型的 Blob,且可以用在任意的 Blob 類型的 context 中。Blob 的屬性和方法都可以用于 File 對(duì)象。

          在 JavaScript 中,主要有兩種方法來獲取 File 對(duì)象:

          <input> 元素上選擇文件后返回的 FileList 對(duì)象;文件拖放操作生成的 DataTransfer 對(duì)象

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

          這里給 input 標(biāo)簽添加了三個(gè)屬性:

          type="file":指定 input 的輸入類型為文件

          id="fileInput":指定 input 的唯一 id

          multiple="multiple":指定 input 可以同時(shí)上傳多個(gè)文件

          下面來給 input 標(biāo)簽添加 onchange 事件,當(dāng)選擇文件并上傳之后觸發(fā):

          const fileInput = document.getElementById("fileInput");
          
          fileInput.onchange = (e) => {
              console.log(e.target.files);
          }

          當(dāng)點(diǎn)擊上傳文件時(shí),控制臺(tái)就會(huì)輸出一個(gè) FileList 數(shù)組,這個(gè)數(shù)組的每個(gè)元素都是一個(gè) File 對(duì)象,一個(gè)上傳的文件就對(duì)應(yīng)一個(gè) File 對(duì)象

          每個(gè) File 對(duì)象都包含文件的一些屬性,這些屬性都繼承自 Blob 對(duì)象:

          • lastModified:引用文件最后修改日期,為自1970年1月1日0:00以來的毫秒數(shù)
          • lastModifiedDate:引用文件的最后修改日期
          • name:引用文件的文件名
          • size:引用文件的文件大小
          • type:文件的媒體類型(MIME)
          • webkitRelativePath:文件的路徑或 URL

          通常,我們?cè)谏蟼魑募r(shí),可以通過對(duì)比 size 屬性來限制文件大小,通過對(duì)比 type 來限制上傳文件的格式等。

          另一種獲取 File 對(duì)象的方式就是拖放 API,這個(gè) API 很簡(jiǎn)單,就是將瀏覽器之外的文件拖到瀏覽器窗口中,并將它放在一個(gè)成為拖放區(qū)域的特殊區(qū)域中。拖放區(qū)域用于響應(yīng)放置操作并從放置的項(xiàng)目中提取信息。這些是通過 ondrop 和 ondragover 兩個(gè) API 實(shí)現(xiàn)的。

          下面來看一個(gè)簡(jiǎn)單的例子,首先定義一個(gè)拖放區(qū)域:

          <div id="drop-zone"></div>

          然后給這個(gè)元素添加 ondragover 和 ondrop 事件處理程序:

          const dropZone = document.getElementById("drop-zone");
          
          dropZone.ondragover = (e) => {
              e.preventDefault();
          }
          
          dropZone.ondrop = (e) => {
              e.preventDefault();
              const files = e.dataTransfer.files;
              console.log(files)
          }

          注意:這里給兩個(gè) API 都添加了 e.preventDefault(),用來阻止默認(rèn)事件。它是非常重要的,可以用來阻止瀏覽器的一些默認(rèn)行為,比如放置文件將顯示在瀏覽器窗口中。

          當(dāng)拖放文件到拖放區(qū)域時(shí),控制臺(tái)就會(huì)輸出一個(gè) FileList 數(shù)組,該數(shù)組的每一個(gè)元素都是一個(gè) File 對(duì)象。這個(gè) FileList 數(shù)組是從事件參數(shù)的 dataTransfer 屬性的 files 獲取的

          FileReader

          FileReader 是一個(gè)異步 API,用于讀取文件并提取其內(nèi)容以供進(jìn)一步使用。FileReader 可以將 Blob 讀取為不同的格式。

          const reader = new FileReader();

          FileReader 對(duì)象提供了以下方法來加載文件:

          • readAsArrayBuffer():讀取指定 Blob 中的內(nèi)容,完成之后,result 屬性中保存的將是被讀取文件的 ArrayBuffer 數(shù)據(jù)對(duì)象
          • readAsBinaryString():讀取指定 Blob 中的內(nèi)容,完成之后,result 屬性中將包含所讀取文件的原始二進(jìn)制數(shù)據(jù)
          • readAsDataURL():讀取指定 Blob 中的內(nèi)容,完成之后,result 屬性中將包含一個(gè)data: URL 格式的 Base64 字符串以表示所讀取文件的內(nèi)容
          • readAsText():讀取指定 Blob 中的內(nèi)容,完成之后,result 屬性中將包含一個(gè)字符串以表示所讀取的文件內(nèi)容

          FileReader 對(duì)象常用的事件如下:

          • abort:該事件在讀取操作被中斷時(shí)觸發(fā)
          • error:該事件在讀取操作發(fā)生錯(cuò)誤時(shí)觸發(fā)
          • load:該事件在讀取操作完成時(shí)觸發(fā)
          • progress:該事件在讀取 Blob 時(shí)觸發(fā)

          當(dāng)然,這些方法可以加上前置 on 后在HTML元素上使用,比如onload、onerror、onabort、onprogress。除此之外,由于FileReader對(duì)象繼承自EventTarget,因此還可以使用 addEventListener() 監(jiān)聽上述事件。

          const fileInput = document.getElementById("fileInput");
          
          const reader = new FileReader();
          
          fileInput.onchange = (e) => {
              reader.readAsText(e.target.files[0]);
          }
          
          reader.onload = (e) => {
              console.log(e.target.result);
          }

          這里,首先創(chuàng)建了一個(gè) FileReader 對(duì)象,當(dāng)文件上傳成功時(shí),使用 readAsText() 方法讀取 File 對(duì)象,當(dāng)讀取操作完成時(shí)打印讀取結(jié)果。

          使用上述例子讀取文本文件時(shí),就是比較正常的。如果讀取二進(jìn)制文件,比如png格式的圖片,往往會(huì)產(chǎn)生亂碼. 那該如何處理這種二進(jìn)制數(shù)據(jù)呢?readAsDataURL() 是一個(gè)不錯(cuò)的選擇,它可以將讀取的文件的內(nèi)容轉(zhuǎn)換為 base64 數(shù)據(jù)的 URL 表示。這樣,就可以直接將 URL 用在需要源鏈接的地方,比如 img 標(biāo)簽的 src 屬性。

          const fileInput = document.getElementById("fileInput");
          
          const reader = new FileReader();
          
          fileInput.onchange = (e) => {
              reader.readAsDataURL(e.target.files[0]);
          }
          
          reader.onload = (e) => {
              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);
          };

          當(dāng)上傳大文件時(shí),可以通過 progress 事件來監(jiān)控文件的讀取進(jìn)度:

          ArrayBuffer

          ArrayBuffer 對(duì)象用來表示通用的、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。ArrayBuffer 的內(nèi)容不能直接操作,只能通過 DataView 對(duì)象或 TypedArrray 對(duì)象來訪問。這些對(duì)象用于讀取和寫入緩沖區(qū)內(nèi)容。

          ArrayBuffer 本身就是一個(gè)黑盒,不能直接讀寫所存儲(chǔ)的數(shù)據(jù),需要借助以下視圖對(duì)象來讀寫:

          • TypedArray:用來生成內(nèi)存的視圖,通過9個(gè)構(gòu)造函數(shù),可以生成9種數(shù)據(jù)格式的視圖。
          • DataViews:用來生成內(nèi)存的視圖,可以自定義格式和字節(jié)序。

          TypedArray視圖和 DataView視圖的區(qū)別主要是字節(jié)序,前者的數(shù)組成員都是同一個(gè)數(shù)據(jù)類型,后者的數(shù)組成員可以是不同的數(shù)據(jù)類型。

          那 ArrayBuffer 與 Blob 有啥區(qū)別呢?根據(jù) ArrayBuffer 和 Blob 的特性,Blob 作為一個(gè)整體文件,適合用于傳輸;當(dāng)需要對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行操作時(shí)(比如要修改某一段數(shù)據(jù)時(shí)),就可以使用 ArrayBuffer。

          ArrayBuffer 有哪些常用的方法和屬性。

          new ArrayBuffer(bytelength)

          ArrayBuffer()構(gòu)造函數(shù)可以分配指定字節(jié)數(shù)量的緩沖區(qū),其參數(shù)和返回值如下:

          • 參數(shù):它接受一個(gè)參數(shù),即 bytelength,表示要?jiǎng)?chuàng)建數(shù)組緩沖區(qū)的大小(以字節(jié)為單位)
          • 返回值:返回一個(gè)新的指定大小的ArrayBuffer對(duì)象,內(nèi)容初始化為0。
          const buffer = new ArrayBuffer(16); 
          console.log(buffer.byteLength);  // 16

          ArrayBuffer 實(shí)例上還有一個(gè) slice 方法,該方法可以用來截取 ArrayBuffer 實(shí)例,它返回一個(gè)新的 ArrayBuffer ,它的內(nèi)容是這個(gè) ArrayBuffer 的字節(jié)副本,從 begin(包括),到 end(不包括)。來看例子:

          const buffer = new ArrayBuffer(16); 
          console.log(buffer.slice(0, 8));  // 16

          這里會(huì)從 buffer 對(duì)象上將前8個(gè)字節(jié)生成一個(gè)新的ArrayBuffer對(duì)象。這個(gè)方法實(shí)際上有兩步操作,首先會(huì)分配一段指定長(zhǎng)度的內(nèi)存,然后拷貝原來ArrayBuffer對(duì)象的置頂部分。

          ArrayBuffer 上有一個(gè) isView()方法,它的返回值是一個(gè)布爾值,如果參數(shù)是 ArrayBuffer 的視圖實(shí)例則返回 true,例如類型數(shù)組對(duì)象或 DataView 對(duì)象;否則返回 false。簡(jiǎn)單來說,這個(gè)方法就是用來判斷參數(shù)是否是 TypedArray 實(shí)例或者 DataView 實(shí)例:

          const buffer = new ArrayBuffer(16);
          ArrayBuffer.isView(buffer)   // false
          
          const view = new Uint32Array(buffer);
          ArrayBuffer.isView(view)     // true

          TypedArray 對(duì)象一共提供 9 種類型的視圖,每一種視圖都是一種構(gòu)造函數(shù)

          元素

          類型化數(shù)組

          字節(jié)

          描述

          Int8

          Int8Array

          1

          8 位有符號(hào)整數(shù)

          Uint8

          Uint8Array

          1

          8 位無符號(hào)整數(shù)

          Uint8C

          Uint8ClampedArray

          1

          8 位無符號(hào)整數(shù)

          Int16

          Int16Array

          2

          16 位有符號(hào)整數(shù)

          Uint16

          Uint16Array

          2

          16 位無符號(hào)整數(shù)

          Int32

          Int32Array

          4

          32 位有符號(hào)整數(shù)

          Uint32

          Uint32Array

          4

          32 位無符號(hào)整數(shù)

          Float32

          Float32Array

          4

          32 位浮點(diǎn)

          Float64

          Float64Array

          8

          64 位浮點(diǎn)

          • Uint8Array: 將 ArrayBuffer 中的每個(gè)字節(jié)視為一個(gè)整數(shù),可能的值從 0 到 255 (一個(gè)字節(jié)等于 8 位)。 這樣的值稱為“8 位無符號(hào)整數(shù)”。
          • Uint16Array:將 ArrayBuffer 中任意兩個(gè)字節(jié)視為一個(gè)整數(shù),可能的值從 0 到 65535。 這樣的值稱為“16 位無符號(hào)整數(shù)”。
          • Uint32Array: 將 ArrayBuffer 中任何四個(gè)字節(jié)視為一個(gè)整數(shù),可能值從 0 到 4294967295,這樣的值稱為“32 位無符號(hào)整數(shù)”。

          這些構(gòu)造函數(shù)生成的對(duì)象統(tǒng)稱為 TypedArray 對(duì)象。它們和正常的數(shù)組很類似,都有l(wèi)ength 屬性,都能用索引獲取數(shù)組元素,所有數(shù)組的方法都可以在類型化數(shù)組上面使用。

          那類型化數(shù)組和數(shù)組有什么區(qū)別呢?

          • 類型化數(shù)組的元素都是連續(xù)的,不會(huì)為空;
          • 類型化數(shù)組的所有成員的類型和格式相同;
          • 類型化數(shù)組元素默認(rèn)值為 0;
          • 類型化數(shù)組本質(zhì)上只是一個(gè)視圖層,不會(huì)存儲(chǔ)數(shù)據(jù),數(shù)據(jù)都存儲(chǔ)在更底層的 ArrayBuffer 對(duì)象中。

          TypedArray 的語法如下(TypedArray只是一個(gè)概念,實(shí)際使用的是那9個(gè)對(duì)象):

          new Int8Array(length);
          new Int8Array(typedArray);
          new Int8Array(object);
          new Int8Array(buffer [, byteOffset [, length]]);

          TypedArray(typeArray) :接收一個(gè)視圖實(shí)例作為參數(shù)

          const view = new Int8Array(new Uint8Array(6));
          view[0] = 10;
          view[3] = 6;
          console.log(view);

          需要注意,TypedArray視圖會(huì)開辟一段新的內(nèi)存,不會(huì)在原數(shù)組上建立內(nèi)存。當(dāng)然,這里創(chuàng)建的類型化數(shù)組也能轉(zhuǎn)換回普通數(shù)組:

          Array.prototype.slice.call(view); // [10, 2, 3, 6, 5]

          每種視圖的構(gòu)造函數(shù)都有一個(gè) BYTES_PER_ELEMENT 屬性,表示這種數(shù)據(jù)類型占據(jù)的字節(jié)數(shù):

          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 屬性也可以在類型化數(shù)組的實(shí)例上獲取:

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

          DataView

          說完 ArrayBuffer,下面來看看另一種操作 ArrayBuffer 的方式:DataView。DataView 視圖是一個(gè)可以從 二進(jìn)制 ArrayBuffer 對(duì)象中讀寫多種數(shù)值類型的底層接口,使用它時(shí),不用考慮不同平臺(tái)的字節(jié)序問題。

          DataView視圖提供更多操作選項(xiàng),而且支持設(shè)定字節(jié)序。本來,在設(shè)計(jì)目的上,ArrayBuffer對(duì)象的各種TypedArray視圖,是用來向網(wǎng)卡、聲卡之類的本機(jī)設(shè)備傳送數(shù)據(jù),所以使用本機(jī)的字節(jié)序就可以了;而DataView視圖的設(shè)計(jì)目的,是用來處理網(wǎng)絡(luò)設(shè)備傳來的數(shù)據(jù),所以大端字節(jié)序或小端字節(jié)序是可以自行設(shè)定的。

          • buffer:一個(gè)已經(jīng)存在的 ArrayBuffer 對(duì)象,DataView 對(duì)象的數(shù)據(jù)源。
          • byteOffset:可選,此 DataView 對(duì)象的第一個(gè)字節(jié)在 buffer 中的字節(jié)偏移。如果未指定,則默認(rèn)從第一個(gè)字節(jié)開始。
          • byteLength:可選,此 DataView 對(duì)象的字節(jié)長(zhǎng)度。如果未指定,這個(gè)視圖的長(zhǎng)度將匹配 buffer 的長(zhǎng)度。
          const buffer = new ArrayBuffer(16);
          const view = new DataView(buffer);
          console.log(view);
          

          ② buffer、byteLength、byteOffset

          DataView實(shí)例有以下常用屬性:

          • buffer:返回對(duì)應(yīng)的ArrayBuffer對(duì)象;
          • byteLength:返回占據(jù)的內(nèi)存字節(jié)長(zhǎng)度;
          • byteOffset:返回當(dāng)前視圖從對(duì)應(yīng)的ArrayBuffer對(duì)象的哪個(gè)字節(jié)開始。

          DataView 實(shí)例提供了以下方法來讀取內(nèi)存,它們的參數(shù)都是一個(gè)字節(jié)序號(hào),表示開始讀取的字節(jié)位置:

          • getInt8:讀取1個(gè)字節(jié),返回一個(gè)8位整數(shù)。
          • getUint8:讀取1個(gè)字節(jié),返回一個(gè)無符號(hào)的8位整數(shù)。
          • getInt16:讀取2個(gè)字節(jié),返回一個(gè)16位整數(shù)。
          • getUint16:讀取2個(gè)字節(jié),返回一個(gè)無符號(hào)的16位整數(shù)。
          • getInt32:讀取4個(gè)字節(jié),返回一個(gè)32位整數(shù)。
          • getUint32:讀取4個(gè)字節(jié),返回一個(gè)無符號(hào)的32位整數(shù)。
          • getFloat32:讀取4個(gè)字節(jié),返回一個(gè)32位浮點(diǎn)數(shù)。
          • getFloat64:讀取8個(gè)字節(jié),返回一個(gè)64位浮點(diǎn)數(shù)。
          const buffer = new ArrayBuffer(24);
          const view = new DataView(buffer);
          
          // 從第1個(gè)字節(jié)讀取一個(gè)8位無符號(hào)整數(shù)
          const view1 = view.getUint8(0);
          
          // 從第2個(gè)字節(jié)讀取一個(gè)16位無符號(hào)整數(shù)
          const view2 = view.getUint16(1);
          
          // 從第4個(gè)字節(jié)讀取一個(gè)16位無符號(hào)整數(shù)
          const view3 = view.getUint16(3);
          

          DataView 實(shí)例提供了以下方法來寫入內(nèi)存,它們都接受兩個(gè)參數(shù),第一個(gè)參數(shù)表示開始寫入數(shù)據(jù)的字節(jié)序號(hào),第二個(gè)參數(shù)為寫入的數(shù)據(jù):

          • setInt8:寫入1個(gè)字節(jié)的8位整數(shù)。
          • setUint8:寫入1個(gè)字節(jié)的8位無符號(hào)整數(shù)。
          • setInt16:寫入2個(gè)字節(jié)的16位整數(shù)。
          • setUint16:寫入2個(gè)字節(jié)的16位無符號(hào)整數(shù)。
          • setInt32:寫入4個(gè)字節(jié)的32位整數(shù)。
          • setUint32:寫入4個(gè)字節(jié)的32位無符號(hào)整數(shù)。
          • setFloat32:寫入4個(gè)字節(jié)的32位浮點(diǎn)數(shù)。
          • setFloat64:寫入8個(gè)字節(jié)的64位浮點(diǎn)數(shù)。

          Object URL

          其實(shí) Blob URL/Object URL 是一種偽協(xié)議,允許將 Blob 和 File 對(duì)象用作圖像、二進(jìn)制數(shù)據(jù)下載鏈接等的 URL 源。

          對(duì)于 Blob/File 對(duì)象,可以使用 URL構(gòu)造函數(shù)的 createObjectURL() 方法創(chuàng)建將給出的對(duì)象的 URL。這個(gè) URL 對(duì)象表示指定的 File 對(duì)象或 Blob 對(duì)象。我們可以在<img>、<script> 標(biāo)簽中或者 <a> 和 <link> 標(biāo)簽的 href 屬性中使用這個(gè) URL。 :

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

          再來使用 URL.createObjectURL() 將File 對(duì)象轉(zhuǎn)化為一個(gè) URL:

          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);
          };
          
          const objUrl = URL.createObjectURL(new File([""], "filename"));
          console.log(objUrl);
          URL.revokeObjectURL(objUrl);
          

          Base64

          Base64 是一種基于64個(gè)可打印字符來表示二進(jìn)制數(shù)據(jù)的表示方法。Base64 編碼普遍應(yīng)用于需要通過被設(shè)計(jì)為處理文本數(shù)據(jù)的媒介上儲(chǔ)存和傳輸二進(jìn)制數(shù)據(jù)而需要編碼該二進(jìn)制數(shù)據(jù)的場(chǎng)景。這樣是為了保證數(shù)據(jù)的完整并且不用在傳輸過程中修改這些數(shù)據(jù)。

          在 JavaScript 中,有兩個(gè)函數(shù)被分別用來處理解碼和編碼 base64 字符串:

          • atob():解碼,解碼一個(gè) Base64 字符串;
          • btoa():編碼,從一個(gè)字符串或者二進(jìn)制數(shù)據(jù)編碼一個(gè) Base64 字符串。
          btoa("JavaScript")       // 'SmF2YVNjcmlwdA=='
          atob('SmF2YVNjcmlwdA==') // 'JavaScript'
          

          那 base64 的實(shí)際應(yīng)用場(chǎng)景有哪些呢?其實(shí)多數(shù)場(chǎng)景就是基于Data URL的。比如,使用toDataURL()方法把 canvas 畫布內(nèi)容生成 base64 編碼格式的圖片:

          const canvas = document.getElementById('canvas'); 
          const ctx = canvas.getContext("2d");
          const dataUrl = canvas.toDataURL();
          

          除此之外,還可以使用readAsDataURL()方法把上傳的文件轉(zhuǎn)為base64格式的data URI,比如上傳頭像展示或者編輯:

          <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 格式進(jìn)行展示,img標(biāo)簽和background的 url 屬性都支持使用base64 格式的圖片,這樣做也可以減少 HTTP 請(qǐng)求。

          看完這些基本的概念,下面就來看看常用格式之間是如何轉(zhuǎn)換的。

          ArrayBuffer → blob

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

          ArrayBuffer → base64

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

          base64 → 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

          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

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

          blob → Object URL

          const objectUrl = URL.createObjectURL(blob);

          、Blob(Binary Large Object)定義:二進(jìn)制類型的大對(duì)象數(shù)據(jù),在 JavaScript 中 Blob 對(duì)象表示不可變的原始數(shù)據(jù)。

          2、語法:

          var aBlob = new Blob(blobParts, options);

          其中:blobParts是一個(gè)由 ArrayBuffer、Blob、DOMString 等對(duì)象構(gòu)成的數(shù)組;options是一個(gè)可選項(xiàng),由type和endings組成,type代表了被放入到 blob 中的內(nèi)容的 MIME 類型,endings用于指定包含行結(jié)束符 \n 的字符串如何被表示(native表示行結(jié)束符\n被更改為適合宿主操作系統(tǒng)的換行符,transparent會(huì)保持 blob 中保存的行結(jié)束符不變)。

          定義Blob

          3、Blob屬性和方法:兩個(gè)只讀屬性size和type,其中size屬性用于表示數(shù)據(jù)的大小(以字節(jié)為單位),type 屬性為MIME 類型的字符串。slice([start[, end[, contentType]]])返回一個(gè)源指定范圍內(nèi)的Blob 對(duì)象;stream()返回一個(gè)讀取 blob 內(nèi)容的ReadableStream;text()返回一個(gè) Promise 對(duì)象且包含 blob 所有內(nèi)容的 UTF-8 格式的 USVString;arrayBuffer()返回一個(gè) Promise 對(duì)象且包含 blob 所有內(nèi)容的二進(jìn)制格式的 ArrayBuffer。

          Blob屬性和方法

          4、Blob URL/Object URL 是一種偽協(xié)議,允許 Blob作為鏈接的URL源,如a.href、img.src等。

          創(chuàng)建 Blob URLurl=URL.createObjectURL(Blob),覽器器為 URL.createObjectURL 生成的 URL 存儲(chǔ)了一個(gè) URL → Blob 映射,此類 URL 較短,例如

          blob:http://domain/b3ad7623-60bb-4eff-9b9d-f925438b97c7

          Blob 本身仍駐留在內(nèi)存中,在不需要時(shí),可以調(diào)用URL.revokeObjectURL(url)來刪除引用。

          5、base64也可以作為<img src= />的源,格式為

          data:[<mediatype>][;base64],<data>

          其中mediatype 是個(gè)MIME 類型的字符串,如 image/png,默認(rèn)值為 text/plain;charset=US-ASCII,例如:

          <img src="data:image/png;base64,R0lGODlheABaAPf/AAC...">



          lob對(duì)象介紹

          一個(gè)Blob對(duì)象表示一個(gè)不可變的,原始數(shù)據(jù)的類似文件對(duì)象。Blob表示的數(shù)據(jù)不一定是一個(gè)JavaScript原生格式blob對(duì)象本質(zhì)上是js中的一個(gè)對(duì)象,里面可以儲(chǔ)存大量的二進(jìn)制編碼格式的數(shù)據(jù)。

          創(chuàng)建blob對(duì)象

          創(chuàng)建blob對(duì)象本質(zhì)上和創(chuàng)建一個(gè)其他對(duì)象的方式是一樣的,都是使用Blob()的構(gòu)造函數(shù)來進(jìn)行創(chuàng)建。構(gòu)造函數(shù)接受兩個(gè)參數(shù):

          第一個(gè)參數(shù)為一個(gè)數(shù)據(jù)序列,可以是任意格式的值。

          第二個(gè)參數(shù)是一個(gè)包含兩個(gè)屬性的對(duì)象{type:MIME的類型,endings:決定第一個(gè)參數(shù)的數(shù)據(jù)格式,可以取值為"transparent"或者"native"(transparent的話不變,是默認(rèn)值,native的話按操作系統(tǒng)轉(zhuǎn)換)。}

          Blob()構(gòu)造函數(shù)允許使用其他對(duì)象創(chuàng)建一個(gè)Blob對(duì)象,比如用字符串構(gòu)建一個(gè)blob


          既然是對(duì)象,那么blob也擁有自己的屬性以及方法

          屬性

          布爾值,指示Blob.close()是否在該對(duì)象上調(diào)用過。關(guān)閉的blob對(duì)象不可讀。

          Blob對(duì)象中所包含數(shù)據(jù)的大小(字節(jié))。

          一個(gè)字符串,表明該Blob對(duì)象所包含數(shù)據(jù)的MIME類型。如果類型未知,則該值為空字符串。

          方法

          關(guān)閉Blob對(duì)象,以便能釋放底層資源。

          返回一個(gè)新的Blob對(duì)象,包含了源Blob對(duì)象中指定范圍內(nèi)的數(shù)據(jù)。其實(shí)就是對(duì)這個(gè)blob中的數(shù)據(jù)進(jìn)行切割,我們?cè)趯?duì)文件進(jìn)行分片上傳的時(shí)候需要使用到這個(gè)方法。

          看到上面這些方法和屬性,使用過HTML5提供的File接口的應(yīng)該都很熟悉,這些屬性和方法在File接口中也都有。其實(shí)File接口就是基于Blob,繼承blob功能并將其擴(kuò)展為支持用戶系統(tǒng)上的文件,也就是說:

          File接口中的Flie對(duì)象就是繼承與Blob對(duì)象。

          blob對(duì)象的使用

          上面說了很多關(guān)于Blob對(duì)象的一些概念性的東西,下面我們來看看實(shí)際用途。

          分片上傳

          首先說說分片上傳,我們?cè)谶M(jìn)行文件上傳的時(shí)候,因?yàn)榉?wù)器的限制,會(huì)限制每一次上傳到服務(wù)器的文件大小不會(huì)很大,這個(gè)時(shí)候我們就需要把一個(gè)需要上傳的文件進(jìn)行切割,然后分別進(jìn)行上傳到服務(wù)器。

          假如需要做到這一步,我們需要解決兩個(gè)問題:

          首先怎么切割的問題上面已經(jīng)有過說明,因?yàn)镕ile文件對(duì)象是繼承與Blob對(duì)象的,因此File文件對(duì)象也擁有slice這個(gè)方法,我們可以使用這個(gè)方法將任何一個(gè)File文件進(jìn)行切割。

          代碼如下:


          通過上面的方法。我們就得到了一個(gè)切割之后的File對(duì)象組成的數(shù)組blobs;

          接下來要做的時(shí)候就是講這些文件分別上傳到服務(wù)器。

          在HTTP1.1以上的協(xié)議中,有Transfer-Encoding這個(gè)編碼協(xié)議,用以和服務(wù)器通信,來得知當(dāng)前分片傳遞的文件進(jìn)程。

          這樣解決了這兩個(gè)問題,我們不僅可以對(duì)文件進(jìn)行分片上傳,并且能夠得到文件上傳的進(jìn)度。

          粘貼圖片

          blob還有一個(gè)應(yīng)用場(chǎng)景,就是獲取剪切板上的數(shù)據(jù)來進(jìn)行粘貼的操作。例如通過QQ截圖后,需要在網(wǎng)頁上進(jìn)行粘貼操作。

          粘貼圖片我們需要解決下面幾個(gè)問題

          首先我們可以通過paste事件來監(jiān)聽用戶的粘貼操作:


          然后通過事件對(duì)象中的clipboardData對(duì)象來獲取圖片的文件數(shù)據(jù)。

          clipboardData對(duì)象介紹

          介紹一下clipboardData對(duì)象,它實(shí)際上是一個(gè)DataTransfer類型的對(duì)象,DataTransfer是拖動(dòng)產(chǎn)生的一個(gè)對(duì)象,但實(shí)際上粘貼事件也是它。

          clipboardData的屬性介紹


          items介紹

          items是一個(gè)DataTransferItemList對(duì)象,自然里面都是DataTransferItem類型的數(shù)據(jù)了。

          屬性

          items的DataTransferItem有兩個(gè)屬性kind和type


          方法


          在原型上還有一些其他方法,不過在處理剪切板操作的時(shí)候一般用不到了。

          type介紹

          一般types中常見的值有text/plain、text/html、Files。


          有了上面這些方法,我們可以解決第二個(gè)問題即獲取到剪切板上的數(shù)據(jù)。


          最后我們需要將獲取到的數(shù)據(jù)渲染到網(wǎng)頁上。

          其實(shí)這個(gè)本質(zhì)上就是一個(gè)類似于上傳圖片本地瀏覽的問題。我們可以直接通過HTML5的File接口將獲取到的文件上傳到服務(wù)器然后通過講服務(wù)器返回的url地址來對(duì)圖片進(jìn)行渲染。也可以使用fileRender對(duì)象來進(jìn)行圖片本地瀏覽。

          fileRender對(duì)象簡(jiǎn)介

          從Blob中讀取內(nèi)容的唯一方法是使用FileReader。

          FileReader接口有4個(gè)方法,其中3個(gè)用來讀取文件,另一個(gè)用來中斷讀取。無論讀取成功或失敗,方法并不會(huì)返回讀取結(jié)果,這一結(jié)果存儲(chǔ)在result屬性中。


          FileReader接口包含了一套完整的事件模型,用于捕獲讀取文件時(shí)的狀態(tài)。


          通過上面的方法以及事件,我們可以發(fā)現(xiàn),通過readAsDataURL方法及onload事件就可以拿到一個(gè)可本地瀏覽圖片的DataURL。

          最終代碼如下:


          這樣我們就可以監(jiān)聽到用戶的粘貼操作,并且將用戶粘貼的圖片文件實(shí)時(shí)的渲染到網(wǎng)頁之中了。

          總結(jié)

          以上是我對(duì)Blob對(duì)象的一些學(xué)習(xí)分享,希望在實(shí)際應(yīng)用上能對(duì)大家有所幫助。也希望大家多多支持小編。


          主站蜘蛛池模板: 无码福利一区二区三区| 亚洲国产国产综合一区首页| 无码人妻精一区二区三区| 久久亚洲日韩精品一区二区三区 | 风间由美在线亚洲一区| 日本一区二区三区在线网| 99无码人妻一区二区三区免费 | 波多野结衣一区二区| 国产精品毛片一区二区三区| 国产伦精品一区二区三区四区 | 老熟妇高潮一区二区三区| 亚洲国产AV一区二区三区四区 | 国产精品一区二区三区免费| 综合激情区视频一区视频二区| 麻豆va一区二区三区久久浪| 综合一区自拍亚洲综合图区| 精品人妻少妇一区二区三区不卡| 色一乱一伦一图一区二区精品| 久久综合九九亚洲一区| 99久久精品午夜一区二区| 日韩在线视频不卡一区二区三区 | 国产在线精品一区二区在线看| 国产精品久久亚洲一区二区| 亚洲第一区精品观看| 亚洲福利视频一区| 国产精品无码一区二区三区在 | 精品女同一区二区三区免费播放| 国偷自产视频一区二区久| 国产av成人一区二区三区| 亚洲精品精华液一区二区| 亚洲av成人一区二区三区在线观看| 国产一区视频在线| 精品国产一区在线观看| 国产午夜精品一区二区三区漫画| 暖暖免费高清日本一区二区三区 | 精品免费国产一区二区三区 | 亚洲国产成人久久一区WWW | 无码人妻久久一区二区三区免费丨| 午夜视频在线观看一区二区| 美女视频在线一区二区三区| 国产精品亚洲一区二区三区久久 |