FileSystemFileHandle: createWritable() 方法

安全上下文:此功能仅在安全上下文(HTTPS)中,以及某些或所有支持的浏览器中可用。

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

createWritable() 方法是 FileSystemFileHandle 接口的一部分,它创建一个 FileSystemWritableFileStream,可用于写入文件。该方法返回一个 Promise,该 Promise 解析为创建的流。

通过流进行的任何更改都不会反映在文件句柄代表的文件中,直到流关闭。这通常通过将数据写入临时文件来实现,并且仅在可写文件流关闭时用临时文件替换文件句柄代表的文件。

语法

js
createWritable()
createWritable(options)

参数

options 可选

具有以下属性的对象

keepExistingData 可选

一个 Boolean。默认值为 false。当设置为 true 时,如果文件存在,则先将现有文件复制到临时文件。否则,临时文件将为空。

mode 可选 非标准

一个字符串,指定可写文件流的锁定模式。默认值为 "siloed"。可能的值为

"exclusive"

只能打开一个 FileSystemWritableFileStream 写入器。在第一个写入器关闭之前尝试打开后续写入器会导致抛出 NoModificationAllowedError 异常。

"siloed"

可以在同一时间打开多个 FileSystemWritableFileStream 写入器,每个写入器都有自己的交换文件,例如在多个选项卡中使用同一个应用程序时。最后一个打开的写入器将写入其数据,因为数据在每个写入器关闭时被刷新。

返回值

一个 Promise,它解析为一个 FileSystemWritableFileStream 对象。

异常

NotAllowedError DOMException

如果句柄的 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="filetext">Enter text to write to the file:</label>
    <input type="text" id="filetext" name="filetext" 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("#filetext");

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

浏览器兼容性

BCD 表格仅在启用 JavaScript 的浏览器中加载。

另请参阅