關於 Blob

博客地址:https://ainyi.com/88

對於 Blob,前端開發中可能比較少遇到;數據庫中可使用 Blob 概念,例如 Mysql 存儲二進制數據的類型就是 Blob,也就是說圖片可存儲於數據庫中,以二進制格式存儲

Blob 對象表示一個不可變、原始數據的類文件對象。File 接口基於Blob,繼承了 blob 的功能並將其擴展使其支持用戶系統上的文件

Blob 是二進制數據對象,是類文件對象的二進制數據

我在之前有篇博客說到 Blob:利用 Blob 處理 Node 層返回的二進制文件流字符串並下載文件
這裏我利用 Blob 實現文件拆分再合併下載的方法,算是第一次使用


我們最常見的應該是 Blob URL 技術,文件上傳的預覽、視頻播放的 src,均是採用這種技術實現

WechatIMG6.png

WechatIMG5.png

Blob URL 就是以 blob: 開頭的一段地址,指向的是一個二進制數據
使用 URL.createObjectURL(blob) 方法生成,參數爲 Blob 對象

這個 Blob URL 是可以直接訪問的;需要注意的是這個 URL 的生效時間,等同於網頁的存在時間,一旦網頁刷新或關閉,這個 Blob URL 就失效

構造函數

Blob(blobParts[, options])

返回一個新創建的 Blob 對象,其內容由參數中給定的數組串聯組成

參數說明:
blobParts:數組類型,數組中的每一項連接起來構成 Blob 對象的數據,數組中的每項元素可以是ArrayBuffer, ArrayBufferView, Blob, DOMString

options:可選參數;字典格式類型,可以指定如下兩個屬性:

  1. type:放入到 blob 中的數組內容的 MIME 類型 MIME 參考手冊
  2. endings:用於指定包含行結束符\n的字符串如何被寫入;可設置值:native、transparent;native:表示行結束符會被更改爲適合宿主操作系統文件系統的換行符; transparent:表示會保持blob中保存的結束符不變;默認值爲 transparent;

使用場景

介紹三種使用場景

  1. 二進制流文件下載
  2. 圖片預覽
  3. 視頻加載

二進制流文件下載

// 獲取文件二進制流 content
const content = await downloadContract(params)

// 再利用 Buffer 轉爲對象
const buf = Buffer.from(content, 'binary')

// 生成 Blob 對象,type 類型設置爲 pdf 的 MIME 類型
const blob = new Blob([buf], {type: 'application/pdf'});

// 獲取 Blob URL,可賦值到 a 標籤 href 屬性進行下載
const url = URL.createObjectURL(blob)

通過 Blob 生成文件、利用 Blob URL 獲取下載鏈接,這樣就實現後端返回二進制格式的文件進行合併再下載

圖片預覽

較爲簡單,獲取文件對象後,再通過 createObjectURL 方法得到 Blob URL
最後直接賦值到 img 標籤的 src 屬性即可

<input id="upload" type="file" />
<img id="preview" src="" alt="預覽"/>
const upload = document.querySelector('#upload')
const preview = document.querySelector('#preview')

upload.onchange = function() {
  const file = upload.files[0] // File 對象
  const src = URL.createObjectURL(file)
  preview.src = src
}

視頻加載

視頻地址,不同於上面的 input,可以直接拿到 File 對象
只有一個視頻地址怎麼能將這個 URL 變成我們想要的 Blob URL 形式呢

URL.createObjectURL(blob) 方法來看,首先要拿到存儲這個視頻原始數據的 Blob 對象

平時我們請求接口可以使用 axios / ajax / xhr 或 fetch,請求一個服務端地址可以返回我們相應的數據,那如果我們去請求一個圖片或視頻地址會返回什麼?應當是返回圖片和視頻的數據,這種情況只要設置正確responseType才能拿到我們想要的格式數據

// responseType 參數如下:
// text 字符串;blob Blob對象;arraybuffer ArrayBuffer 對象
function ajax(url, cb) {
  const xhr = new XMLHttpRequest()
  xhr.open('get', url)
  xhr.responseType = 'blob'
  xhr.onload = function() {
    cb(xhr.response)
  }
  xhr.send()
}

上面請求返回一個 Blob 對象,接下來只要然後通過 createObjectURL 生成 Blob URL 賦值給視頻的 src 屬性就可以了

ajax('video.mp4', function(res){
  const src = URL.createObjectURL(res)
  video.src = src
})

大文件分片上傳

最近看到一篇文章:大規格文件的上傳優化

裏面講的是利用 Blob 實現文件分片上傳,對於大文件上傳有很好的效果

其核心思想是文件分片,使用 File.slice() 方法進行文件分片;File 對象是繼承 Blob 對象的,因此 File 對象也有 slice 方法

Blob.slice([start[, end[, contentType]]])

start 可選
這個參數代表 Blob 裏的下標,表示第一個會被會被拷貝進新的 Blob 的字節的起始位置。如果你傳入的是一個負數,那麼這個偏移量將會從數據的末尾從後到前開始計算
舉例來說: -10 將會是 Blob 的倒數第十個字節。它的默認值是0, 如果你傳入的start的長度大於源 Blob 的長度,那麼返回的將會是一個長度爲0並且不包含任何數據的一個 Blob 對象

end 可選
這個參數代表的是 Blob 的一個下標,這個下標-1的對應的字節將會是被拷貝進新的Blob 的最後一個字節。如果你傳入了一個負數,那麼這個偏移量將會從數據的末尾從後到前開始計算
舉例來說: -10 將會是 Blob 的倒數第十個字節。它的默認值就是它的原始長度(size)

contentType 可選
給新的 Blob 賦予一個新的文檔類型。這將會把它的 type 屬性設爲被傳入的值。它的默認值是一個空的字符串


文件分片方法
定義每一個分片文件的大小變量爲 chunkSize,通過文件大小 FileSize 和分片大小 chunkSize 得到分片數量 chunks,使用 for 循環和 file.slice() 方法對文件進行分片,序號爲 0 - n,和已上傳的切片列表做比對,得到所有未上傳的分片,push 到請求列表 requestList

上傳進度
監聽原生 Javascript 的 XMLHttpRequest 的 progress 事件,這個事件會返回文件已上傳的大小和總大小,可實現上傳進度的變化

博客地址:https://ainyi.com/88

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章