認識Js中的二進制數據


Blob

在項目中涉及到要對html原生的audio組件進行樣式復寫,因此需要重新實現audio的一些功能,比如下載。實現一個下載大致的思路是服務端返回一段音頻的二進制數據,客戶端將其存放在Blob中,再通過URL.createObjectURL將其轉換成blob url,最后動態創建a標簽,添加download屬性,模擬點擊事件來實現下載。代碼比較簡單,我們重點來看看Blob是何方神聖。

const saveExcelFile = (blob, filename) => {
    if (window.navigator.msSaveOrOpenBlob) {
      // iE下使用msSaveBlob進行導出
      navigator.msSaveBlob(blob, filename)
    } else {
      var href = window.URL.createObjectURL(blob)

      var save_link = document.createElementNS(
        'http://www.w3.org/1999/xhtml',
        'a'
      )
      save_link.href = href
      save_link.download = filename

      // 解決火狐兼容問題
      document.body.appendChild(save_link)

      var event = document.createEvent('MouseEvents')
      event.initMouseEvent(
        'click',
        true,
        false,
        window,
        0,
        0,
        0,
        0,
        0,
        false,
        false,
        false,
        false,
        0,
        null
      )
      save_link.dispatchEvent(event)

      document.body.removeChild(save_link)
      // 釋放blob url,可被GC回收
      window.URL.revokeObjectURL(href)
    }
}

根據MDN的介紹,我們可以知道Blob類型的對象是類似文件對象的二進制數據,它是immutable的,即數據不可變。而HTML5的File對象繼承於Blob對象,並在其基礎上做了些擴展,從而具備了在操作系統上操作文件的能力。我們可以利用Blob去做一些下載文件、分片上傳等功能。熟悉ES6的小伙伴應該知道,ES6中有一個ArrayBuffer對象,也是用來存儲二進制數據的,那它和Blob有什么區別呢?

ArrayBuffer

根據一些資料,ArrayBuffer設計的目的與WebGL項目有關,為了滿足JS與顯卡或聲卡等操作系統原生接口大量的、實時的數據交換。傳統的文本格式是傳遞一個32位的整數,這導致JS與原生接口需要頻繁的轉換數據格式,效率較低,因此設計了ArrayBuffer用於存儲、操作二進制數據。
ArrayBuffer並不是真正的Array,而是個類數組對象。我們通過new ArrayBuffer(length)創建的ArrayBuffer的實例,僅僅代表開辟了一段連續的內存空間,length代表內存所占的字節大小。若需要對內存中的字節進行操作,則需要創建“視圖”。視圖分為兩種:TypedArray和DataView,用於以指定的格式來讀寫二進制的數據。它們的區別在於:

  • TypedArray以指定的格式讀寫內存,例如:const v1 = new Int32Array(buffer)就是以32位有符號整型來創建視圖,此時通過v1[0]去讀或是去寫都是以該格式進行的
  • 若是想以不同數據格式去讀取內存的話,需要使用DataView。當我們執行const dv = new DataView(buffer)后,可以通過類似dv.getUint8(0)這樣的方式,以8位無符號整型讀取第一個字節;或是以dv.setInt32(1, 25)這種方式,在第二個字節寫入值為25的32位有符號整型數據

注意:對於同一段內存創建的視圖都是共享該內存的,在一個視圖上進行的操作會影響另一個視圖的讀寫。具體的可參考阮老師的教程

區別

  • ArrayBuffer可以對字節進行讀寫,而Blob是immutable的
  • ArrayBuffer存儲在內存當中,Blob可以存儲在磁盤或者內存中。例如文件,我們平時是存在磁盤中的。而像我們上面下載的例子中,我們的blob是在內存中的,因此在createObjectURL之后需要手動調用revokeObjectURL解除對內存的引用,使得blob可以被GC回收,釋放內存。
  • ArrayBuffer可以通過“視圖”來進行讀寫,而Blob可以通過FileReader去讀,但是不能寫
  • Blob和ArrayBuffer可以互相轉換。Blob轉ArrayBuffer可以通過:
    const reader = new FileReader()
    reader.onload = function() {
        console.log(reader.result)
    }
    reader.readAsArrayBuffer(blob)
    
    ArrayBuffer轉Blob可以通過:
    const blob = new Blob([ArrayBuffer])
    

因此,當我們需要對字節進行操作的時候,我們應該選用ArrayBuffer,否則,我們用Blob會更加容易。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM