原文地址:https://codeburst.io/javascri...作者:Dornhoth
如果你已經能讓一個使用者從你的網站上下載某些檔案,那或許你已經遇到過 Blob 型別了。你可能已經在網上檢查了一些例子並修改它們,但沒有多想這個 Blob 是什麼。只要它能工作...
這種知識可以顯示初級開發人員和高階開發人員之間的區別。又或者,作為一名初級開發人員,你會因為好奇和渴望學習而脫穎而出。即使你不是在為面試做準備,對 Blob 是什麼有一個清晰而簡單的理解,也可以幫助你理解下一次在壓縮 PDF 檔案時,中間遇到的複雜程式碼,所以我們開始吧:
用法
要下載一些簡單的文字,你可以這樣做:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Blobs</title>
<script src="index.js"></script>
</head>
<body>
<button id="button">Link</button>
</body>
</html>
const download = (fileName, file) => {
const element = document.createElement('a');
element.href = file;
element.download = fileName;
element.target = '_blank';
element.click();
element.remove();
}
document.addEventListener('click', async event => {
if (event.target.id === 'button') {
const fileName = 'test.txt';
download(fileName, 'data:text/json;charset=utf-8,File to download');
}
});
另一方面,對於更復雜的檔案,這還不夠。如果我們想下載生成 PDF 檔案,則必須這樣做(這個示例使用 jsPDF):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Blobs</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.3.5/jspdf.debug.js"></script>
<script src="index.js"></script>
</head>
<body>
<button id="button">Link</button>
</body>
</html>
const download = (fileName, blob) => {
const element = document.createElement('a');
const url = window.URL.createObjectURL(blob);
element.href = url;
element.download = fileName;
element.target = '_blank';
element.click();
element.remove();
}
document.addEventListener('click', async event => {
if (event.target.id === 'button') {
const doc = new jsPDF();
const fileName = 'test.pdf';
doc.text('Hello world!');
const blob = new Blob([doc.output()]);
download(fileName, blob);
}
});
什麼是Blob?
Blob 不是 JavaScript 特有的。最初,建立 Blob 是為了在資料庫管理系統中使用。該型別建立於1970年代,用於儲存音訊、影像或視訊等大檔案,這些檔案太大,無法儲存在常規資料庫欄位中。因此這個術語實際上是指“二進位制大物件”。
在 JavaScript 中,Blob 用於將檔案表示為不可變的原始資料。在控制檯中,我們在前面的例子中建立的 Blob,如下所示:
如你所見,Blob 有兩個屬性:大小(size)和型別(type)。大小是以位元組為單位的資料大小。型別是一個包 MIME 型別的字串。建立 Blob 時我沒有給出任何型別,但我應該這樣做:
const blob = new Blob([doc.output()], { type: 'application/pdf' });
現在我的 Blob 也有一個型別:
Blob中有什麼?
JavaScript Blob 提供了一些方法來訪問它們的內容。其中一個是 text 方法,它以文字(text)形式返回對 Blob 內容的 Promise 解析(技術上是 USVString)。
document.addEventListener('click', async event => {
if (event.target.id === 'button') {
const doc = new jsPDF();
doc.text('Hello world!');
const blob = new Blob([doc.output()], { type: 'application/pdf' });
const blobAsText = await blob.text();
console.log(blobAsText);
}
});
這給了我們一個相當不好理解的內容:
%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Resources 2 0 R
/MediaBox [0 0 595.28 841.89]
/Contents 4 0 R
>>
endobj
4 0 obj
<</Length 67>>
stream
0.57 w
0 G
BT
/F1 16 Tf
18.4 TL
0 g
NaN NaN Td
(Hello world!) Tj
ET
endstream
endobj
1 0 obj
<</Type /Pages
/Kids [3 0 R ]
/Count 1
>>
endobj
5 0 obj
<</BaseFont/Helvetica/Type/Font
/Encoding/WinAnsiEncoding
/Subtype/Type1>>
endobj
6 0 obj
...
能做的事情並不多,但它給了你一個機會,讓你瞭解檔案內部長什麼樣子。
還有另外兩種方法可以讓你訪問 Blob 的內容:
- arrayBuffer,將返回一個 Promise 解析到 ArrayBuffer
- stream,將返回一個可讀流(ReadableStream)
操作 Blob
你定期從 HTTP 請求接收檔案。如果使用 fetch API,則需要使用 body 上的 blob 方法從響應中讀取 blob:
document.addEventListener('click', async event => {
if (event.target.id === 'button') {
fetch('https://whatever/doc.pdf')
.then(response => response.blob())
.then(blob => {
download('test.pdf', blob);
});
}
});
在前面的示例中,我們使用庫建立了一個 PDF 檔案,並從中建立了一個 Blob。
你還可以從另一個 Blob 建立一個 Blob。您只能對原始 Blob 進行切片(slice),也就是說只返回其位元組的一部分。
document.addEventListener('click', async event => {
if (event.target.id === 'button') {
const blob = new Blob(['some text'], { type: 'application/pdf' });
const slicedBlob = blob.slice(5, 9);
const blobAsText = await blob.text();
const slicedBlobAsText = await slicedBlob.text();
console.log(`Original Blob: ${blobAsText}`);
console.log(`Sliced Blob: ${slicedBlobAsText}`);
}
});
這對於非常簡單的 Blob 可能很有用,但是對於更復雜的檔案,這可能會損壞您的檔案並使切片的 Blob 不可讀。
我希望你現在能理解 Blob 的用法。這是一種非常簡單的資料型別,用於將檔案表示為原始資料。如果您想了解更多細節,可以檢視文件: