Web 開發中 Blob 與 FileAPI 使用簡述

本文節選自 Awesome CheatSheet/DOM CheatSheet,主要是對 DOM 操做中常見的 Blob、File API 相關概念進行簡要描述。css

Web 開發中 Blob 與 FileAPI 使用簡述

Blob 是 JavaScript 中的對象,表示不可變的類文件對象,裏面能夠存儲大量的二進制編碼格式的數據。Blob 對象的建立方式與其餘並沒有區別,構造函數可接受數據序列與類型描述兩個參數:git

const debug = { hello: 'world' };
let blob = new Blob([JSON.stringify(debug, null, 2)], {
  type: 'application/json'
});
// Blob(22) {size: 22, type: "application/json"}

// 也能夠轉化爲類 URL 格式
const url = URL.createObjectURL(blob);
// "blob:https://developer.mozilla.org/88c5b6de-3735-4e02-8937-a16cc3b0e852"

// 設置自定義的樣式類
blob = new Blob(['body { background-color: yellow; }'], {
  type: 'text/css'
});

link = document.createElement('link');
link.rel = 'stylesheet';
//createObjectURL returns a blob URL as a string.
link.href = URL.createObjectURL(blob);
複製代碼

其餘的類型轉化爲 Blob 對象能夠參考 covertToBlob.js,將 Base64 編碼的字符串或者 DataUrl 轉化爲 Blob 對象。Blob 包括了 size 與 type,以及經常使用的用於截取的 slice 方法等屬性。Blob 對象可以添加到表單中,做爲上傳數據使用:github

const content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file...
const blob = new Blob([content], { type: 'text/xml' });

formData.append('webmasterfile', blob);
複製代碼

slice 方法會返回一個新的 Blob 對象,包含了源 Blob 對象中指定範圍內的數據。其實就是對這個 blob 中的數據進行切割,咱們在對文件進行分片上傳的時候須要使用到這個方法,即把一個須要上傳的文件進行切割,而後分別進行上傳到服務器:web

const BYTES_PER_CHUNK = 1024 * 1024; // 每一個文件切片大小定爲1MB .
const blob = document.getElementById('file').files[0];
const slices = Math.ceil(blob.size / BYTES_PER_CHUNK);
const blobs = [];
Array.from({ length: slices }).forEach(function(item, index) {
  blobs.push(blob.slice(index, index + 1));
});
複製代碼

這裏咱們使用的 blob 對象其實是 HTML5 中的 File 對象;HTML5 File API 容許咱們對本地文件進行讀取、上傳等操做,主要包含三個對象:File,FileList 與用於讀取數據的 FileReader。File 對象就是 Blob 的分支,或者說子集,表示包含某些元數據的單一文件對象;FileList 便是文件對象的列表。FileReader 可以用於從 Blob 對象中讀取數據,包含了一系列讀取文件的方法與事件回調,其基本用法以下:json

const reader = new FileReader();
reader.addEventListener('loadend', function() {
  // reader.result 包含了 Typed Array 格式的 Blob 內容
});
reader.readAsArrayBuffer(blob);

blob = new Blob(['This is my blob content'], { type: 'text/plain' });
read.readAsText(bolb); // 讀取爲文本

// reader.readAsArrayBuffer //將讀取結果封裝成 ArrayBuffer ,若是想使用通常須要轉換成 Int8Array 或 DataView
// reader.readAsBinaryString // 在IE瀏覽器中不支持改方法
// reader.readAsTex // 該方法有兩個參數,其中第二個參數是文本的編碼方式,默認值爲 UTF-8
// reader.readAsDataURL // 讀取結果爲DataURL
// reader.readyState // 上傳中的狀態
複製代碼

在圖片上傳中,咱們經常須要獲取到本地圖片的預覽,參考 antd/Upload 中的處理:瀏覽器

// 將文件讀取爲 DataURL
const previewFile = (file: File, callback: Function) => {
  const reader = new FileReader();
  reader.onloadend = () => callback(reader.result);
  reader.readAsDataURL(file);
};

// 設置文件的 DataUrl
previewFile(file.originFileObj, (previewDataUrl: string) => {
  file.thumbUrl = previewDataUrl;
});

// JSX
<img src={file.thumbUrl || file.url} alt={file.name} />;
複製代碼

另外一個經常使用的場景就是獲取剪貼板中的圖片,並將其預覽展現,能夠參考 coding-snippets/image-paste:服務器

const cbd = e.clipboardData;
const fr = new FileReader();

for (let i = 0; i < cbd.items.length; i++) {
  const item = cbd.items[i];

  if (item.kind == 'file') {
    const blob = item.getAsFile();
    if (blob.size === 0) {
      return;
    }

    previewFile(blob);
  }
}
複製代碼

標準的 Web 標準中提供了 FileReader 對象進行讀取操做,不過 Chrome 中提供了 FileWriter 對象,容許咱們在瀏覽器沙盒中建立文件,其基於 requestFileSystem 方法:antd

// 僅可用於 Chrome 瀏覽器中
window.requestFileSystem =
  window.requestFileSystem || window.webkitRequestFileSystem;

window.requestFileSystem(type, size, successCallback, opt_errorCallback);
複製代碼

簡單的文件建立與寫入以下所示:app

function onInitFs(fs) {
  fs.root.getFile(
    'log.txt',
    { create: true },
    function(fileEntry) {
      // Create a FileWriter object for our FileEntry (log.txt).
      fileEntry.createWriter(function(fileWriter) {
        fileWriter.onwriteend = function(e) {
          console.log('Write completed.');
        };

        fileWriter.onerror = function(e) {
          console.log('Write failed: ' + e.toString());
        };

        // Create a new Blob and write it to log.txt.
        var blob = new Blob(['Lorem Ipsum'], { type: 'text/plain' });

        fileWriter.write(blob);
      }, errorHandler);
    },
    errorHandler
  );
}

window.requestFileSystem(window.TEMPORARY, 1024 * 1024, onInitFs, errorHandler);
複製代碼
相關文章
相關標籤/搜索