FileSystemFileHandle: createWritable() 方法

基準線 2025
新推出

自 ⁨2025 年 9 月⁩起,此功能適用於最新裝置和瀏覽器版本。此功能可能不適用於較舊的裝置或瀏覽器。

安全上下文: 此功能僅在安全上下文(HTTPS)中可用,且支援此功能的瀏覽器數量有限。

注意:此功能在 Web Workers 中可用。

FileSystemFileHandle 介面的 createWritable() 方法建立一個 FileSystemWritableFileStream,該流可用於向檔案寫入資料。該方法返回一個 Promise,該 Promise 會解析為建立的流。

透過流進行的任何更改在流關閉之前都不會反映在檔案控制代碼所表示的檔案中。這通常是透過將資料寫入臨時檔案來實現的,只有在可寫檔案流關閉時,才會用臨時檔案替換檔案控制代碼所表示的檔案。

語法

js
createWritable()
createWritable(options)

引數

options 可選

具有以下屬性的物件:

keepExistingData 可選

一個 Boolean 值。預設為 false。如果設定為 true 且檔案存在,則會將現有檔案首先複製到臨時檔案中。否則,臨時檔案將從空開始。

mode 可選 非標準

一個字串,指定可寫檔案流的鎖定模式。預設值為 "siloed"。可能的值包括:

"exclusive"

一次只能開啟一個 FileSystemWritableFileStream 寫入器。在第一個寫入器關閉之前嘗試開啟後續寫入器將丟擲 NoModificationAllowedError 異常。

"siloed"

可以同時開啟多個 FileSystemWritableFileStream 寫入器,每個寫入器都有自己的交換檔案,例如當同一應用程式在多個標籤頁中使用時。當每個寫入器關閉並重新整理資料時,最後一個開啟的寫入器的資料會被寫入。

返回值

一個 Promise,它會解析為一個 FileSystemWritableFileStream 物件。

異常

NotAllowedError DOMException

如果控制代碼在 readwrite 模式下的 PermissionStatus.state 不是 'granted',則丟擲此異常。

NotFoundError DOMException

如果當前條目未找到,則丟擲此異常。

NoModificationAllowedError DOMException

如果瀏覽器無法獲取與檔案控制代碼關聯的檔案的鎖,則丟擲此異常。這可能是因為 mode 設定為 exclusive 並且嘗試同時開啟多個寫入器。

AbortError DOMException

如果實現定義的惡意軟體掃描和安全瀏覽檢查失敗,則丟擲此異常。

示例

基本用法

以下非同步函式會將給定內容寫入檔案控制代碼,進而寫入磁碟。

js
async function writeFile(fileHandle, contents) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();

  // Write the contents of the file to the stream.
  await writable.write(contents);

  // Close the file and write the contents to disk.
  await writable.close();
}

使用選項的擴充套件用法

我們的 createWritable() 模式測試 示例(請參閱 原始碼)提供了一個 <button> 用於選擇要寫入的檔案,一個文字 <input> 欄位,您可以在其中輸入要寫入檔案的文字,以及第二個 <button> 用於將文字寫入檔案。

在上面的演示中,請嘗試選擇檔案系統上的一個文字檔案(或輸入一個新的檔名),在輸入欄位中輸入一些文字,然後將文字寫入檔案。開啟檔案系統上的檔案以檢查寫入是否成功。

另外,請嘗試同時在兩個瀏覽器標籤頁中開啟該頁面。在第一個標籤頁中選擇一個要寫入的檔案,然後立即在第二個標籤頁中嘗試選擇同一個檔案進行寫入。您應該會收到一條錯誤訊息,因為我們在 createWritable() 呼叫中設定了 mode: "exclusive"

下面我們將探討程式碼。

HTML

兩個 <button> 元素和文字 <input> 欄位如下所示:

html
<ol>
  <li>
    Select a file to write to: <button class="select">Select file</button>
  </li>
  <li>
    <label for="file-text">Enter text to write to the file:</label>
    <input type="text" id="file-text" name="file-text" disabled />
  </li>
  <li>
    Write your text to the file:
    <button class="write" disabled>Write text</button>
  </li>
</ol>

文字輸入欄位和寫入文字按鈕最初透過 disabled 屬性設定為停用狀態——在使用者選擇要寫入的檔案之前不應使用它們。

JavaScript

我們首先獲取對選擇檔案按鈕、寫入文字按鈕和文字輸入欄位的引用。我們還聲明瞭一個全域性變數 writableStream,一旦建立,它將儲存對用於將文字寫入檔案的可寫流的引用。我們最初將其設定為 null

js
const selectBtn = document.querySelector(".select");
const writeBtn = document.querySelector(".write");
const fileText = document.querySelector("#file-text");

let writableStream = null;

接下來,我們建立一個名為 selectFile() 的非同步函式,當按下選擇按鈕時呼叫它。此函式使用 Window.showSaveFilePicker() 方法向用戶顯示一個檔案選擇器對話方塊,並建立使用者選擇的檔案的控制代碼。在該控制代碼上,我們呼叫 createWritable() 方法來建立一個將文字寫入所選檔案的流。如果呼叫失敗,我們會將錯誤記錄到控制檯。

我們將 createWritable() 傳遞一個包含以下選項的物件:

  • keepExistingData: true:如果所選檔案已存在,則在開始寫入之前,會將其中包含的資料複製到臨時檔案中。
  • mode: "exclusive":表示一次只能開啟一個寫入器。如果第二個使用者載入示例並嘗試選擇一個檔案,他們將收到一個錯誤。

最後,我們啟用輸入欄位和寫入文字按鈕,因為它們是下一步所必需的,並停用選擇檔案按鈕(當前不需要)。

js
async function selectFile() {
  // Create a new handle
  const handle = await window.showSaveFilePicker();

  // Create a FileSystemWritableFileStream to write to
  try {
    writableStream = await handle.createWritable({
      keepExistingData: true,
      mode: "exclusive",
    });
  } catch (e) {
    if (e.name === "NoModificationAllowedError") {
      console.log(
        `You can't access that file right now; someone else is trying to modify it. Try again later.`,
      );
    } else {
      console.log(e.message);
    }
  }

  // Enable text field and write button, disable select button
  fileText.disabled = false;
  writeBtn.disabled = false;
  selectBtn.disabled = true;
}

我們的下一個函式 writeFile() 使用 FileSystemWritableFileStream.write() 將輸入欄位中輸入的文字寫入所選檔案,然後清空輸入欄位。然後我們使用 WritableStream.close() 關閉可寫流,並重置演示以便再次執行——控制元件的 disabled 狀態會切換回其原始狀態,並且 writableStream 變數會重置為 null

js
async function writeFile() {
  // Write text to our file and empty out the text field
  await writableStream.write(fileText.value);
  fileText.value = "";

  // Close the file and write the contents to disk.
  await writableStream.close();

  // Disable text field and write button, enable select button
  fileText.disabled = true;
  writeBtn.disabled = true;
  selectBtn.disabled = false;

  // Set writableStream back to null
  writableStream = null;
}

為了執行演示,我們在按鈕上設定了事件監聽器,以便在每次單擊按鈕時執行相應的函式。

js
selectBtn.addEventListener("click", selectFile);
writeBtn.addEventListener("click", writeFile);

規範

規範
檔案系統
# api-filesystemfilehandle-createwritable

瀏覽器相容性

另見