JavaScript Blob 物件

admin發表於2019-01-01

Blob的英文全稱是Binary Large Object,翻譯成漢語是二進位制大型物件。

HTML5中,Blob是一種JavaScript資料型別,用於儲存二進位制資料。

此物件中儲存的資料沒有必要非得是JavaScript原生格式資料,也就是沒必要是JavaScript內部物件。

比如可以是File物件,它繼承Blob物件,並擴充套件了一些功能。

一.建立Blob物件:

建立Blob物件的方式有多種,下面首先做一下概念介紹,最後再通過程式碼例項演示。

1.建構函式方式:

這是最為基礎的方式,與其他建構函式建立物件例項完全一樣。

語法結構:

[JavaScript] 純文字檢視 複製程式碼
let blob = new Blob(array, options);

引數解析:

(1).array:必需,陣列,陣列成員可以是二進位制物件或者字串。

(2).options:可選,物件,用於設定陣列中資料的MIME型別。

2.slice()方式:

此方法是Blob物件例項方法,通過它可以基於原始的Blob物件,建立一個新的Blob物件。

語法結構:

[JavaScript] 純文字檢視 複製程式碼
blob.slice(start,end, contentType)

引數解析:

(1).start:可選,預設值為0,規定開始拷貝二進位制資料的位置,以位元組計數。

(2).end:可選,預設值為Blob物件的size屬性值,但是此值不在拷貝範圍之內,以位元組計數。

(3).contentType:可選,預設值為空,規定新Blob物件的型別。

特別說明:

(1).start和end引數用於規定拷貝的範圍。

(2).start和end引數值可以是負數,如果是負數,表示從資料的結尾開始計數,0表示資料的第一個位元組,那麼很自然-1就是資料的倒數第一個位元組,兩個引數負數的原理是一致的。

3.canvas物件的toBlob方法:

從此方法的名稱也大致能夠猜測到它的功能。

canvas物件呼叫此方法,就會將其轉換為一個Blob物件,後面會有程式碼演示。

二.屬性與方法:

(1).size屬性:可以返回當前物件的位元組長度。

(2).type屬性:可以返回資料的型別,全部為小寫,如果型別未知,則該值為空字串。

(3).slice方法:在前面已經介紹了,可以拷貝原有Blob物件,生成一個新Blob物件。

三.程式碼例項:

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let arr = ['<div>螞蟻部落</div>'];
let blob = new Blob(arr, {type: 'text/html'});
console.log(blob.size);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102218xhg505y04yp0zxy3.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

通過建構函式建立一個包含DOMString型別資料的Blob物件。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let buffer = new ArrayBuffer(8);
let blob = new Blob([buffer], {type: 'text/plain'});
console.log(blob.size);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102256j54e24pj6i4ojlr2.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

通過建構函式建立一個包含ArrayBuffer型別資料的Blob物件。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let buffer = new ArrayBuffer(32);
let intArray=new Int16Array(buffer);
let blob = new Blob([intArray], {type: 'text/plain'});
console.log(blob.size);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102339qtw2zv7wtktm7mch.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

ArrayBuffer只表示一段連續的記憶體區域,但是運算元據需要型別化陣列的配合。

關於arrayBuffer物件的用法參閱JavaScript ArrayBuffer一章節。

[JavaScript] 純文字檢視 複製程式碼執行程式碼
let blob = new Blob(["abcdefgh"], {type: 'text/plain'});
let newB=blob.slice(1,5);
console.log(newB.size);

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102528t68v1c9c40k8fsk0.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).物件中的位元組索引位置是從0開始計數的。

(2).slice方法會擷取索引位置1到5(不包含)之間的資料,也就是4個位元組。

(3).所以列印結果為4。

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<script>
window.onload=function(){
  let canvas = document.getElementById("canvas");
  let ctx = canvas.getContext("2d");
  ctx.lineWidth=10;
  ctx.lineJoin="round";
  ctx.strokeRect(10,10,100,100);
  canvas.toBlob(function(blob){
    console.log(blob);
  });
}
</script>
</head>
<body>
<canvas id="canvas" width="400" height="300"></canvas>
</body>
</html>

程式碼執行效果截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102614c0zcxixx36ecf5z1.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

toBlob方法的回撥函式的引數就是一個機遇canvas生成的Blob物件。

四.實際應用場景:

(1).分段上傳:

如果要上傳的檔案非常的大,那麼使用分段上傳功能是一個非常好的選擇。

可以利用Blob物件的slice方法實現此功能,程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset=" utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<script>
var h = {
  init: function () {
    var _this = this;
 
    document.getElementById("File").onchange = _this.fileHandler;
    document.getElementById("Abort").onclick = _this.abortHandler;
 
    _this.status = document.getElementById("Status");
    _this.progress = document.getElementById("Progress");
    _this.percent = document.getElementById("Percent");
 
    _this.loaded = 0;
    //每次讀取1M  
    _this.step = 1024 * 1024;
    _this.times = 0;
  },
  fileHandler: function (e) {
    var _this = h;
    _this.file = this.files[0];
    _this.reader = new FileReader();
 
    _this.total = _this.file.size;
 
    _this.reader.onloadstart = _this.onLoadStart;
    _this.reader.onprogress = _this.onProgress;
    _this.reader.onabort = _this.onAbort;
    _this.reader.onerror = _this.onerror;
    _this.reader.onload = _this.onLoad;
    _this.reader.onloadend = _this.onLoadEnd;
    //讀取第一塊  
    _this.readBlob(0);
  },
   
  readBlob: function (start) {
    var _this = h;
 
    var blob,
        file = _this.file;
 
    _this.times += 1;
 
    blob = file.slice(start, start + _this.step + 1);
    _this.reader.readAsText(blob);
  },
 
  onLoadStart: function () {
    var _this = h;
  },
 
  onProgress: function (e) {
    var _this = h;
    _this.loaded += e.loaded;
    //更新進度條  
    _this.progress.value = (_this.loaded / _this.total) * 100;
  },
 
  onAbort: function () {
    var _this = h;
  },
  onError: function () {
    var _this = h;
  },
 
  onLoad: function () {
    var _this = h;
 
    if (_this.loaded < _this.total) {
      _this.readBlob(_this.loaded);
    } else {
      _this.loaded = _this.total;
    }
  },
 
  onLoadEnd: function () {
    var _this = h;
  },
   
  abortHandler: function () {
    var _this = h;
 
    if (_this.reader) {
      _this.reader.abort();
    }
  }
};
 
window.onload = function () {
  h.init();
}
</script>
</head>
<body>
<form>
  <fieldset>
    <legend>分度讀取檔案:</legend>
    <input type="file" id="File" />
    <input type="button" value="中斷" id="Abort" />
    <p>
      <label>讀取進度:</label>
      <progress id="Progress" value="0" max="100"></progress>
    </p>
    <p id="Status"></p>
  </fieldset>
</form>  
</body>
</html>

上述程式碼實現分段上傳功能,並且可以進行效果演示,具體程式碼實現大家可以自行分析。

(2).通過url下載檔案:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<script>
function creatUrl(fileName, content){
  let blob = new Blob([content]);
  let link = document.createElement("a");
  link.innerHTML = fileName;
  link.download = fileName;
  link.href = URL.createObjectURL(blob);
  document.getElementsByTagName("body")[0].appendChild(link);
}
window.onload=function(){
  creatUrl("ant.txt","螞蟻部落");
}
</script>
</head>
<body>
</body>
</html>

程式碼執行效果控制檯截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102716u8tx2xqorcrq8er7.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

程式碼分析如下:

(1).首先,將字串生成一個Blob物件。

(2).然後通過URL.createObjectURL方法生成一個對應Blob物件的URL。

(3).URL以blob:開頭,其後是一串識別符號,唯一標識記憶體中的指定Blob物件。

(4).點選動態生成的連結,即可實現下載功能,用到了HTML5新增的download屬性。

關於download屬性可以參閱HTML <a> 標籤一章節。

URL物件也是HTML5新增,尚屬實驗性質,標準化後,螞蟻部落教程會第一時間跟進更新。

同樣的道理,也可以將圖片轉換為Blob物件,然後再使用URL.createObjectURL方法生成一個地址。

最後通過JavaScript賦值給img的src屬性,程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<script>
window.onload=function(){
  let canvas = document.getElementById("canvas");
  let ctx = canvas.getContext("2d");
  ctx.lineWidth=10;
  ctx.lineJoin="round";
  ctx.strokeRect(10,10,100,100);
  canvas.toBlob(function(blob){
    let ant=document.getElementById("ant");
    ant.src=URL.createObjectURL(blob);
  });
}
</script>
</head>
<body>
<canvas id="canvas" width="400" height="150"></canvas>
<br/>
<img id="ant">
</body>
</html>

程式碼執行效果控制檯截圖如下:

a:3:{s:3:\"pic\";s:43:\"portal/201901/01/102759vn8sm9siseks8pb0.png\";s:5:\"thumb\";s:0:\"\";s:6:\"remote\";N;}

AJAX也可以利用Blob物件實現下載功能,可以將responseType屬性設定為blob型別。

程式碼片段如下:

[JavaScript] 純文字檢視 複製程式碼
function getBlob(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', url);
  xhr.responseType = 'blob';
  xhr.onload = function () {
    callback(xhr.response);
  }
  xhr.send(null);
}

上述程式碼返回的就是一個Blob型別物件。

(4).FileReader物件:

通過此物件可以操作Blob物件,考慮到文章的篇幅問題,本文不再介紹。

具體內容可以參閱JavaScript FileReader 物件一章節。

相關文章