天天看點

JavaScript:File API和Blob API

web應用的痛點就是不能操作計算機上的檔案。File API和Blob API可以安全通路到用戶端上的檔案。

File類型

現在我們可以在html表單中直接通路檔案,比如:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
    <input type="file">
</body>
</html>      

效果如圖:

JavaScript:File API和Blob API

當我們選擇檔案後,可以讀出檔案得到名稱:

JavaScript:File API和Blob API

選中後的檔案中,每一個File對象中都隻有一些隻讀屬性,比如name、size和type:

JavaScript:File API和Blob API

FileReader類型

FileReader類型是一種異步檔案讀取機制,提供了集中讀取檔案資料的方法:

readAsText(file,encoding):從檔案中讀取純文字内容并且儲存在result屬性中,第二個參數是表示編碼,可選參數。

readAsDataURL(file):讀取檔案并且将内容的資料URI儲存在result屬性中。

readAsBinaryString(file):讀取檔案并且把每一個字元的二進制資料儲存在result屬性。

readAsArrayBuffer(file):讀取檔案并且把内容以ArrayBuffer形式儲存在result中。

在讀取檔案中,會觸發幾個事件:progress、error和load,表示進度、發生錯誤和讀取完成。

progress事件每50毫秒就會觸發一次,在這期間可以讀取FileReader的result屬性;

error事件,在無法讀取檔案的時候觸發,error屬性是一個對象,隻包含一個屬性:code。這個錯誤碼的值可能是1(未找到檔案)、2(安全錯誤)、3(讀取被中斷)、4(檔案不可讀)或5(編碼錯誤)

load事件會在成功加載後觸發,如果error事件觸發,那麼不會觸發load事件

比如:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file" id="file">

  <div type="text" id="output"></div>

  <div id="progress"></div>
  <script>
    let filesList = document.getElementById("file");
    filesList.addEventListener("change", (event) => {
      let info = "",
          output = document.getElementById("output"),
          progress = document.getElementById("progress"),
          files = event.target.files,
          type = "default",
          reader = new FileReader();
      if (/image/.test(files[0].type)) {
        reader.readAsDataURL(files[0]);
        type = "image";
      } else {
        reader.readAsText(files[0]);
        type = "text";
      }
      reader.onerror = function() {
        output.innerHTML = "Could not read file, error code is " +
            reader.error.code;
      };
      reader.onprogress = function(event) {
        if (event.lengthComputable) {
          console.log(`${event.loaded}/${event.total}`)
          progress.innerHTML = `${event.loaded}/${event.total}`;
        }
      };
      reader.onload = function() {
        let html = "";
        switch(type) {
          case "image":
            html = `<img src="${reader.result}">`;
            break;
          case "text":
            html = reader.result;
            break;
        }
        output.innerHTML = html;
      };
    });
  </script>
</body>

</html>      

Blob

Blob是表示二進制大對象,是JavaScript對不可修改的二進制資料的封裝類型,包含字元串的數組、ArrayBuffers、ArrayBufferViews,

Blob對象有一個size屬性和type屬性,slice方法用于進一步切分資料,另外也可以使用FileReader從Blob中讀取資料。隻讀取一部分檔案可以節省時間,比如現在隻讀取檔案的前10個位元組:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file" id="file">

  <div type="text" id="output"></div>

  <div id="progress"></div>
  <script>
    let filesList = document.getElementById("files-list");
    filesList.addEventListener("change", (event) => {
      let info = "",
        output = document.getElementById("output"),
        progress = document.getElementById("progress"),
        files = event.target.files,
        reader = new FileReader(),
        blob = blobSlice(files[0], 0, 10);
      if (blob) {
        reader.readAsText(blob);
        reader.onerror = function () {
          output.innerHTML = "Could not read file, error code is " +
            reader.error.code;
        };
        reader.onload = function () {
          output.innerHTML = reader.result;
        };
      } else {
        console.log("Your browser doesn't support slice().");
      }
    });
  </script>
</body>

</html>      

Blob URL

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file" id="file" multiple>

  <div type="text" id="output"></div>

  <div id="progress"></div>
  <script>
    let filesList = document.getElementById("file");
    filesList.addEventListener("change", (event) => {
      let info = "",
        output = document.getElementById("output"),
        progress = document.getElementById("progress"),
        files = event.target.files,
        reader = new FileReader(),
        url=window.URL.createObjectURL(files[0]);
        console.log("url",url)
      if (url) {
        if (/image/.test(files[0].type)) {
          output.innerHTML=`<img src="${url}">`;
        } else {
          output.innerHTML = "Not an image.";
        }
      } else {
        output.innerHTML = "Your browser doesn't support object URLs.";
      }
    });
  </script>
</body>

</html>      

繼續閱讀