【譯】什麼是Blob?

諾頓發表於2020-06-30
原文地址: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,如下所示:

image

如你所見,Blob 有兩個屬性:大小(size)和型別(type)。大小是以位元組為單位的資料大小。型別是一個包 MIME 型別的字串。建立 Blob 時我沒有給出任何型別,但我應該這樣做:

const blob = new Blob([doc.output()], { type: 'application/pdf' });

現在我的 Blob 也有一個型別:

image

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}`);
  }
});

image

這對於非常簡單的 Blob 可能很有用,但是對於更復雜的檔案,這可能會損壞您的檔案並使切片的 Blob 不可讀。

我希望你現在能理解 Blob 的用法。這是一種非常簡單的資料型別,用於將檔案表示為原始資料。如果您想了解更多細節,可以檢視文件:

https://developer.mozilla.org/en-US/docs/Web/API/Blob

相關文章