二進制對象:Blob、File和它們的讀取對象:FileReader

一、Blob 對象

Blob,全稱 Binary Large Object,代表二進制類型的大對象。在Web領域,Blob對象表示一個不可變、二進制原始數據的類文件對象,因此可以像操作文件對象一樣操作Blob對象。File 接口基於Blob,繼承了 Blob 的功能並將其擴展使其支持用戶系統上的文件。

一、Blob基本用法

1. 創建Blob對象

生成Blob對象有兩種方法:

  1. 使用Blob構造函數(用於從其他非blob對象和數據構造一個 Blob
  2. 對已有的Blob對象使用slice()方法切出一段(用於創建一個 blob 數據的子集 blob)

1)Blob構造函數

var aBlob = new Blob( array[, options] );

Blob() 構造函數返回一個新的 Blob 對象,其內容由參數數組中給出的值串聯組成。

參數:

     array:是一個由 ArrayBufferArrayBufferViewBlobDOMString 等對象構成的 Array ,或者其他類似對象的混合體,它將會被放進 Blob。DOMStrings會被編碼爲UTF-8。 

     options:配置屬性(可選)。可以指定如下兩個屬性:

             1. type,默認值爲 "",它代表了將會被放入到blob中的數組內容的MIME類型。'text/csv,charset=UTF-8' 設置爲csv格式,並設置編碼爲UTF-8。

             2. endings,默認值爲"transparent",用於指定包含行結束符\n的字符串如何被寫入。 它是以下兩個值中的一個: "native",代表行結束符會被更改爲適合宿主操作系統文件系統的換行符,或者 "transparent",代表會保持blob中保存的結束符不變。

示例:

var data1 = '我是Blob';
var data2 = "<div style='color:red;'>This is a blob</div>"; // DOMString
var data3 = {hello: "world"};

var blob1 = new Blob([data1], {type: 'text/html'});
var blob2 = new Blob([data2], {type: 'text/html'});
var blob3 = new Blob([data1, data2]);
var blob4 = new Blob([JSON.stringify(data3, null, 2)], {type: 'application/json'});

注意:如果要轉成Blob的數據是普通對象,要先用 JSON.stringify() 轉換成字符串。

new Blob([{name: 'abc'}])

上述的寫法會先調用普通對象的toString()方法得到字符串數據,然後再創建Blob對象。所以,上述保存的數據是"[object Object]"。

Blob屬性

blob.size   //Blob大小(以字節爲單位)
blob.type   //Blob的MIME類型,如果是未知,則是""(空字符串)

2)slice() 創建

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

參數說明:

  • start 可選,開始索引,可以爲負數,語法類似於數組的slice方法.默認值爲0.

  • end 可選,結束索引,可以爲負數,語法類似於數組的slice方法.默認值爲最後一個索引.

  • contentType 可選 ,新的Blob對象的MIME類型,這個值將會成爲新的Blob對象的type屬性的值,默認爲一個空字符串.

2. URL.createObjectURL(blob)

該方法用於生成一個 blob URL 指向Blob 。

var url = URL.createObjectURL(blob);
// 會產生一個類似 blob:d3958f5c-0777-0845-9dcf-2cb28783acaf 這樣的URL字符串
// 你可以像使用普通 URL 那樣使用它,比如用在 img.src 上。

3. URL.revokeObjectURL(url)

該方法用來釋放調用 URL.createObjectURL() 生成的 URL 對象。當你結束使用某個 URL 對象時,應該通過調用這個方法來讓瀏覽器知道不再需要保持這個文件的引用了。

var url = URL.createObjectURL(blob);
URL.revokeObjectURL(url);

二、Blob使用場景

1. Blob URL

文件下載地址:

<a download="data.txt" id="getData">下載</a>
var data= 'Hello world!';  
var blob = new Blob([data], {type: 'text/html,charset=UTF-8'});
window.URL = window.URL || window.webkitURL; 
document.querySelector("#getData").href = URL.createObjectURL(blob);

圖片資源地址:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Blob Test</title>
    <script>
        function handleFile(e) {
            var file = e.files[0];
            var blob = URL.createObjectURL(file);
            var img = document.getElementsByTagName("img")[0];
            img.src = blob;
            img.onload = function(e) {
                URL.revokeObjectURL(this.src); // 釋放
            }
        }
    </script>
</head>
<body>
    <input type="file" accept="image/*" οnchange="handleFile(this)" />
    <br/>
    <img style="width:200px;height:200px">
</body>
</html>

使用 createObjectURL(blob) 輸出頁面,移動端長按保存,轉發

2. 大文件分割上傳

主要是利用Blob中 slice() 方法。

function upload(blobOrFile) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/server', true);
  xhr.onload = function(e) { ... };
  xhr.send(blobOrFile);
}

document.querySelector('input[type="file"]').addEventListener('change', function(e) {
  var blob = this.files[0];

  const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes.
  const SIZE = blob.size;

  var start = 0;
  var end = BYTES_PER_CHUNK;

  while(start < SIZE) {
    upload(blob.slice(start, end));

    start = end;
    end = start + BYTES_PER_CHUNK;
  }
}, false);
})();

更詳細內容

3. 隱藏視頻源路徑

var video = document.getElementById('video');
var obj_url = window.URL.createObjectURL(blob);
video.src = obj_url;
video.play()
window.URL.revokeObjectURL(obj_url);

三、從 Blob 中提取數據

一種從Blob中讀取內容的方法是使用 FileReader。以下代碼將 Blob 的內容作爲類型數組讀取:

var reader = new FileReader();
reader.addEventListener("loadend", function() {
   // reader.result 包含被轉化爲類型數組 typed array 的 blob
});
reader.readAsArrayBuffer(blob);

另一種讀取Blob中內容的方式是使用Response對象。下述代碼將Blob中的內容讀取爲文本:

var text = await (new Response(blob)).text();

二、File 對象

文件(File)接口提供有關文件的信息,並允許網頁中的 JavaScript 訪問其內容。

通常情況下, File 對象是來自用戶在一個 <input> 元素上選擇文件後返回的 FileList 對象,也可以是來自由拖放操作生成的 DataTransfer 對象,或者來自 HTMLCanvasElement 上的 mozGetAsFile() API。

File 對象是特殊類型的 Blob,且可以用在任意的 Blob 類型的 context 中。比如說, FileReaderURL.createObjectURL()createImageBitmap(), 及 XMLHttpRequest.send() 都能處理 Blob 和 File

構造函數

var myFile = new File(bits, name[, options]);

返回一個新構建的文件對象(File)。

參數:

  • bitsArrayBufferArrayBufferViewBlob,或者 DOMString 對象的 Array — 或者任何這些對象的組合。這是 UTF-8 編碼的文件內容。
  • name:USVString,表示文件名稱,或者文件路徑。
  • options: 可選。配置屬性。可用的選項如下:

       type: 表示將要放到文件中的內容的 MIME 類型。默認值爲 "" 。

       lastModified: 表示文件最後修改時間的 Unix 時間戳(毫秒)。默認值爲 Date.now()

示例:

var file = new File(["foo"], "foo.txt", {
  type: "text/plain",
});

屬性

1. File.lastModified 

返回當前 File 對象所引用文件最後修改時間,自 UNIX 時間起始值(1970年1月1日 00:00:00 UTC)以來的毫秒數。

2. File.name 

返回當前 File 對象所引用文件的名字。

3. File.size

返回文件的大小。

4. File.type 

返回文件的 MIME Type。

三、FileReader 對象

FileReader 對象允許Web應用程序異步讀取存儲在用戶計算機上的文件(或原始數據緩衝區)的內容,使用 File 或 Blob 對象指定要讀取的文件或數據。

構造函數

var reader = new FileReader();

示例:

function printFile(file) {
  var reader = new FileReader();
  reader.onload = function(evt) {
    console.log(evt.target.result);
  };
  reader.readAsText(file);
}

屬性

1. FileReader.error表示在讀取文件時發生的錯誤 。

2. FileReader.readyState表示FileReader狀態的數字。取值如下:

常量名 描述
EMPTY 0 還沒有加載任何數據.
LOADING 1 數據正在被加載.
DONE 2 已完成全部的讀取請求.

3. FileReader.result文件的內容。該屬性僅在讀取操作完成後纔有效,數據的格式取決於使用哪個方法來啓動讀取操作。

事件處理

以下列了價格主要的事件處理:

1. FileReader.onerror

處理error事件。該事件在讀取操作發生錯誤時觸發。

2. FileReader.onload

處理load事件。該事件在讀取操作完成時觸發。

3. FileReader.onloadend

處理loadend事件。該事件在讀取操作結束時(要麼成功,要麼失敗)觸發。

4. FileReader.onprogress

處理progress事件。該事件在讀取Blob時觸發。

方法

1. FileReader.abort()

中止讀取操作。在返回時,readyState屬性爲DONE

注意:對一個沒有正在進行讀取操作(readyState 不是LOADING)的 FileReader 進行 abort 操作,會拋出 DOM_FILE_ABORT_ERR 錯誤。

2. FileReader.readAsArrayBuffer(blob)

用於啓動讀取指定的 Blob 或 File 內容。當讀取操作完成時,readyState 變成 DONE(已完成),並觸發 loadend 事件,同時 result 屬性中將包含一個 ArrayBuffer 對象以表示所讀取文件的數據。

3. FileReader.readAsDataURL(blob)

讀取指定的 Blob 或 File 對象。讀取操作完成的時候, result 屬性將包含一個data:URL格式的字符串(base64編碼)以表示所讀取文件的內容。
4. FileReader.readAsText()

將 Blob 或者 File 對象轉成指定編碼格式的文本字符串。

FileReader.readAsText(blob[, encoding])

encoding:編碼類型,默認爲“utf-8”類型。

示例

示例1:使用 readAsDataURL()

<input type="file" οnchange="previewFile()"><br>
<img src="" height="200" alt="Image preview...">
function previewFile() {
  var preview = document.querySelector('img');
  var file    = document.querySelector('input[type=file]').files[0];
  var reader  = new FileReader();

  reader.addEventListener("load", function () {
    preview.src = reader.result;
  }, false);

  if (file) {
    reader.readAsDataURL(file);
  }
}

// 也可以寫成如下形式
function previewFile() {
  var preview = document.querySelector('img');
  var file    = document.querySelector('input[type=file]').files[0];
  var reader  = new FileReader();

  // 就這裏不一樣
  reader.onload = function (e) {
    preview.src = e.target.result;
  };

  if (file) {
    reader.readAsDataURL(file);
  }
}

四、Data URL

即前綴爲 data: 協議的的URL,其允許內容創建者向文檔中嵌入小文件。

Data URL 由四個部分組成:

  • 前綴(data:)
  • 指示數據類型的MIME類型
  • 如果非文本則爲可選的base64標記
  • 數據本身
data:[<mediatype>][;base64],<data>

mediatype 是個 MIME 類型的字符串,例如 "image/jpeg" 表示 JPEG 圖像文件。如果被省略,則默認值爲 text/plain;charset=US-ASCII。

如果數據是文本類型,你可以直接將文本嵌入 (根據文檔類型,使用合適的實體字符或轉義字符)。如果是二進制數據,你可以將數據進行base64編碼之後再進行嵌入。

示例:

//簡單的 text/plain 類型數據
data:,Hello%2C%20World!
//上一條示例的 base64 編碼版本
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
//一個HTML文檔源代碼 <h1>Hello, World</h1>
data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E
//一個會執行 JavaScript alert 的 HTML 文檔。
data:text/html,<script>alert('hi');</script>

生成 DataURL 用 FileReaderreadAsDataURL(blob) 方法。

Web性能優化中有一項措施:把小圖片用base64編碼直接嵌入到HTML文件中,實際上就是利用了Data URL來獲取嵌入的圖片數據。

五、Blob URL和Data URL的區別

  1. Blob URL的長度一般比較短,但Data URL因爲直接存儲圖片base64編碼後的數據,往往很長,瀏覽器在顯示Data URL時使用了省略號(…)。當顯式大圖片時,使用Blob URL能獲取更好的可能性。
  2. Blob URL可以方便的使用XMLHttpRequest獲取源數據,例如:
var blobUrl = URL.createObjectURL(new Blob(['Test'], {type: 'text/plain'}));
var x = new XMLHttpRequest();
// 如果設置x.responseType = 'blob',將返回一個Blob對象,而不是文本:
// x.responseType = 'blob';
x.onload = function() {
    alert(x.responseText);   // 輸出 Test
};
x.open('get', blobUrl);
x.send();

對於Data URL,並不是所有瀏覽器都支持通過XMLHttpRequest獲取源數據的。

     3. Blob URL 只能在當前應用內部使用,把Blob URL複製到瀏覽器的地址欄中,是無法獲取數據的。Data URL相比之下,就有很好的移植性,你可以在任意瀏覽器中使用。

除了可以用作圖片資源的網絡地址,Blob URL也可以用作其他資源的網絡地址,例如html文件、json文件等,爲了保證瀏覽器能正確的解析Blob URL返回的文件類型,需要在創建Blob對象時指定相應的type:

// 創建HTML文件的Blob URL
var data = "<div style='color:red;'>This is a blob</div>";
var blob = new Blob([data], { type: 'text/html' });
var blobURL = URL.createObjectURL(blob);

// 創建JSON文件的Blob URL
var data = { "name": "abc" };
var blob = new Blob([JSON.stringify(data)], { type: 'application/json' });
var blobURL = URL.createObjectURL(blob);


 

 

參考文章

 

發佈了122 篇原創文章 · 獲贊 87 · 訪問量 52萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章