2020 年 4 月 9 日

檔案和 FileReader

檔案物件繼承自 Blob,並擴充了與檔案系統相關的功能。

有兩種取得檔案物件的方法。

首先,有一個建構函式,類似於 Blob

new File(fileParts, fileName, [options])
  • fileParts – 是 Blob/BufferSource/String 值的陣列。
  • fileName – 檔案名稱字串。
  • options – 選擇性物件
    • lastModified – 最後修改的時間戳記(整數日期)。

其次,我們更常從 <input type="file"> 或拖放或其他瀏覽器介面取得檔案。在這種情況下,檔案會從作業系統取得這些資訊。

由於 檔案 繼承自 Blob,因此 檔案 物件具有相同的屬性,外加

  • name – 檔案名稱,
  • lastModified – 最後修改的時間戳記。

這就是我們如何從 <input type="file"> 取得 File 物件

<input type="file" onchange="showFile(this)">

<script>
function showFile(input) {
  let file = input.files[0];

  alert(`File name: ${file.name}`); // e.g my.png
  alert(`Last modified: ${file.lastModified}`); // e.g 1552830408824
}
</script>
請注意

輸入可能會選取多個檔案,所以 input.files 是包含這些檔案的陣列類似物件。這裡我們只有一個檔案,所以我們只要取用 input.files[0]

FileReader

FileReader 是用來從 Blob(因此也包括 File)物件讀取資料的物件。

它使用事件傳送資料,因為從磁碟讀取資料可能需要時間。

建構函式

let reader = new FileReader(); // no arguments

主要方法

  • readAsArrayBuffer(blob) – 以二進位格式 ArrayBuffer 讀取資料。
  • readAsText(blob, [encoding]) – 以指定的編碼(預設為 utf-8)將資料讀取為文字字串。
  • readAsDataURL(blob) – 讀取二進位資料並將其編碼為 base64 資料 URL。
  • abort() – 取消操作。

read* 方法的選擇取決於我們偏好的格式以及我們如何使用資料。

  • readAsArrayBuffer – 對於二進位檔案,用於執行低階二進位操作。對於高階操作(例如切片),File 繼承自 Blob,因此我們可以直接呼叫它們,而無需讀取。
  • readAsText – 對於文字檔案,當我們想要取得字串時。
  • readAsDataURL – 當我們想要在 img 或其他標籤的 src 中使用此資料時。有一個替代方案可以讀取檔案,如 Blob 章節中所述:URL.createObjectURL(file)

在讀取過程中,會有事件

  • loadstart – 開始載入。
  • progress – 在讀取期間發生。
  • load – 沒有錯誤,讀取完成。
  • abort – 呼叫 abort()
  • error – 發生錯誤。
  • loadend – 讀取已完成,無論成功或失敗。

讀取完成後,我們可以存取結果,如下所示

  • reader.result 是結果(如果成功)
  • reader.error 是錯誤(如果失敗)。

使用最廣泛的事件肯定是 loaderror

以下是讀取檔案的範例

<input type="file" onchange="readFile(this)">

<script>
function readFile(input) {
  let file = input.files[0];

  let reader = new FileReader();

  reader.readAsText(file);

  reader.onload = function() {
    console.log(reader.result);
  };

  reader.onerror = function() {
    console.log(reader.error);
  };

}
</script>
FileReader for blobs

Blob 章節中所述,FileReader 不僅可以讀取檔案,還可以讀取任何 blob。

我們可以使用它將 blob 轉換為另一種格式

  • readAsArrayBuffer(blob) – 轉換為 ArrayBuffer
  • readAsText(blob, [encoding]) – 轉換為字串(TextDecoder 的替代方案),
  • readAsDataURL(blob) – 轉換為 base64 資料網址。
FileReaderSync 可在 Web Workers 中使用

對於 Web Workers,還存在一個 FileReader 的同步變體,稱為 FileReaderSync

它的讀取方法 read* 不會產生事件,而是像一般函式一樣回傳結果。

不過,這僅限於 Web Worker 內部,因為在 Web Workers 中,從檔案讀取時可能發生的同步呼叫延遲較不重要。它們不會影響網頁。

摘要

File 物件繼承自 Blob

除了 Blob 方法和屬性之外,File 物件還具有 namelastModified 屬性,以及從檔案系統讀取的內部能力。我們通常從使用者輸入(例如 <input> 或拖放事件 (ondragend))取得 File 物件。

FileReader 物件可以從檔案或 blob 讀取,採用三種格式之一

  • 字串 (readAsText)。
  • ArrayBuffer (readAsArrayBuffer)。
  • 資料網址,base-64 編碼 (readAsDataURL)。

不過,在許多情況下,我們不必讀取檔案內容。就像我們對 blob 所做的一樣,我們可以使用 URL.createObjectURL(file) 建立一個短網址,並將其指定給 <a><img>。這樣,檔案就可以下載或顯示為影像,作為畫布的一部分等。

如果我們要透過網路傳送 File,這也很容易:XMLHttpRequestfetch 等網路 API 原生接受 File 物件。

教學課程地圖

留言

留言前請先閱讀以下內容…
  • 如果您有改善建議,請 提交 GitHub 問題 或提出 pull 要求,而不是留言。
  • 如果您無法理解文章中的某些內容,請詳細說明。
  • 要插入幾行程式碼,請使用 <code> 標籤,對於多行,請將它們包在 <pre> 標籤中,對於超過 10 行,請使用沙盒 (plnkrjsbincodepen…)