在 JavaScript 中處理文件,第 5 部分:Blob
到目前為止,本系列文章的重點是與用戶指定並通過 File
訪問的文件進行交互 對象。 File
object 實際上是 Blob
的更具體的版本 ,它表示一大塊二進制數據。 size
和 type
Blob
上存在屬性 對象並由 File
繼承 .
在大多數情況下,Blob
s 和 File
s 可以用在同一個地方。例如,您可以從 Blob
中讀取 使用 FileReader
您可以從 Blob
創建一個對象 URL 使用 URL.createObjectURL()
.
切片
Blob
可以做的一件有趣的事 s(因此,還有 File
s) 就是新建一個Blob
基於另一個小節。由於每個 Blob
只表示指向數據的指針而不是數據本身,可以快速創建新的Blob
指向其他子部分的對象。這是通過使用 slice()
來完成的 方法。
你可能熟悉slice()
字符串和數組,以及 Blob
s 的行為方式類似。該方法接受三個參數:起始字節的偏移量、結束字節的偏移量以及應用於 Blob
的可選 MIME 類型 .如果未指定 MIME 類型,則新的 Blob
與原來的 MIME 類型相同。
slice()
的瀏覽器支持 尚未普及,Firefox 通過 mozSlice()
支持它 和 webkitSlice()
在 Chrome 中(目前沒有其他瀏覽器支持此方法)。舉個例子:
function sliceBlob(blob, start, end, type) {
type = type || blob.type;
if (blob.mozSlice) {
return blob.mozSlice(start, end, type);
} else if (blob.webkitSlice) {
return blob.webkitSlice(start, end type);
} else {
throw new Error("This doesn't work!");
}
}
然後,您可以使用此功能,例如,拆分一個大文件以分塊上傳。每個新的 Blob
即使每個引用的數據有重疊,正在生成的數據也獨立於原始數據。 Flickr 的工程師使用 blob 切片從上傳的照片中讀取 Exif 信息
1
而不是在服務器上等待它。選擇文件後,Flickr 上傳頁面同時開始上傳文件並從照片中讀取 Exif 信息。這允許他們在文件上傳時在頁面中預覽提取的元數據。
以舊方式創建 Blob
File
之後不久 對像開始出現在瀏覽器中,開發人員意識到 Blob
對象實際上非常強大,因此希望能夠在沒有用戶交互的情況下創建它們。畢竟,任何數據都可以用 Blob
表示 ,它不一定必須綁定到文件。瀏覽器通過創建 BlobBuilder
快速響應 ,其唯一目的是將一些數據包裝在 Blob
中的類型 目的。這是一種非標準類型,已在 Firefox 中實現(如 MozBlobBuilder
), Internet Explorer 10 (as MSBlobBuilder
) 和 Chrome (如 WebKitBlobBuilder
)。
BlobBuilder
通過創建一個新實例並調用 append()
來工作 帶有字符串的方法,ArrayBuffer
, 或 Blob
.添加完所有數據後,調用 getBlob()
並傳入一個應該應用於 Blob
的可選 MIME 類型 .舉個例子:
var builder = new BlobBuilder();
builder.append("Hello world!");
var blob = builder.getBlob("text/plain");
為任意數據創建 URL 的能力非常強大,允許您動態創建可以在瀏覽器中作為文件尋址的對象。例如,您可以使用 Blob
在沒有單獨的工作人員代碼文件的情況下創建 Web 工作人員。這個技術寫在 Web Workers 基礎
2
:
// Prefixed in Webkit, Chrome 12, and FF6: window.WebKitBlobBuilder, window.MozBlobBuilder
var bb = new BlobBuilder();
bb.append("onmessage = function(e) { postMessage('msg from worker'); }");
// Obtain a blob URL reference to our worker 'file'.
// Note: window.webkitURL.createObjectURL() in Chrome 10+.
var blobURL = window.URL.createObjectURL(bb.getBlob());
var worker = new Worker(blobURL);
worker.onmessage = function(e) {
// e.data == 'msg from worker'
};
worker.postMessage(); // Start the worker.
此代碼創建一個簡單的腳本,然後創建一個對象 URL。對象 URL 被分配給 Web Worker,而不是腳本 URL。
你可以調用 append()
任意多次,構建 Blob
的內容 .
以新方式創建 Blob
因為開發人員一直在要求一種創建 Blob
的方法 直接對象,瀏覽器提出 BlobBuilder
,決定加一個Blob
構造函數。這個構造函數現在是規範的一部分,將成為 Blob
對像是在未來創建的。
構造函數接受兩個參數。第一個是要組合成 Blob
的部分數組 .這些值與傳遞給 append()
的值相同 BlobBuilder
的方法 並且可以是任意數量的字符串,Blob
s 和 ArrayBuffer
s。第二個參數是一個包含新創建的 Blob
屬性的對象 .目前定義了兩個屬性,type
,它指定 Blob
的 MIME 類型 , 和 endings
,可以是“透明”(默認)或“原生”。舉個例子:
var blob = new Blob(["Hello world!"], { type: "text/plain" });
如您所見,這比使用 BlobBuilder
簡單得多 .
Blob
構造函數目前在 Chrome 的每晚版本中,並將在 Firefox 13 中。其他瀏覽器尚未宣布實施此構造函數的計劃,但是,它現在是 File API 的一部分
3
標準,有望得到普遍實施。
結論
這是在 JavaScript 中處理文件系列的最後一部分。正如我希望你了解的那樣,File API 非常強大,並開闢了在 Web 應用程序中處理文件的全新方式。當用戶需要上傳文件時,您不再需要堅持使用純文件上傳框,現在您可以在客戶端讀取文件,這為客戶端操作提供了各種可能性。您可以在上傳之前調整太大的圖像大小(使用 FileReader
和 <canvas>
);您可以創建一個純粹在瀏覽器中工作的文本編輯器;您可以拆分大文件以逐個上傳。可能性並非無窮無盡,但非常接近。
參考
- Flickr 團隊使用 JavaScript 解析 Exif 客戶端
- Eric Bidelman 的《Web Workers 基礎》
- 文件 API – Blob 構造函數