FileSystemFileHandle:createSyncAccessHandle() 方法
注意:此功能仅在专用 Web 工作线程中可用。
createSyncAccessHandle()
方法是 FileSystemFileHandle
接口的方法,它返回一个 Promise
,该 Promise 解析为一个 FileSystemSyncAccessHandle
对象,该对象可用于同步读取和写入文件。此方法的同步特性带来了性能优势,但它仅可在专用Web 工作线程中用于来源私有文件系统中的文件。
创建 FileSystemSyncAccessHandle
会对与文件句柄关联的文件进行独占锁定。这将阻止创建其他 FileSystemSyncAccessHandle
或 FileSystemWritableFileStream
,直到现有的访问句柄关闭。
语法
createSyncAccessHandle()
createSyncAccessHandle(options)
参数
options
可选-
具有以下属性的对象
mode
可选 非标准-
指定访问句柄锁定模式的字符串。默认值为
"readwrite"
。可能的值为"read-only"
-
可以在一个文件上同时打开多个
FileSystemSyncAccessHandle
对象(例如,在多个选项卡中使用同一个应用程序时),前提是它们都以"read-only"
模式打开。打开后,可以在句柄上调用类似读取的方法——read()
、getSize()
和close()
。 "readwrite"
-
只能在一个文件上打开一个
FileSystemSyncAccessHandle
对象。在第一个句柄关闭之前尝试打开后续句柄会导致抛出NoModificationAllowedError
异常。打开后,可以在句柄上调用任何可用的方法。 "readwrite-unsafe"
-
可以在一个文件上同时打开多个
FileSystemSyncAccessHandle
对象,前提是它们都以"readwrite-unsafe"
模式打开。打开后,可以在句柄上调用任何可用的方法。
返回值
一个 Promise
,它解析为一个 FileSystemSyncAccessHandle
对象。
异常
NotAllowedError
DOMException
-
如果句柄的
PermissionStatus.state
在readwrite
模式下不是granted
,则抛出此异常。 InvalidStateError
DOMException
-
如果
FileSystemSyncAccessHandle
对象不代表 来源私有文件系统中的文件,则抛出此异常。 NotFoundError
DOMException
-
如果找不到当前条目,则抛出此异常。
NoModificationAllowedError
DOMException
-
如果浏览器无法获取与文件句柄关联的文件的锁定,则抛出此异常。这可能是因为
mode
设置为readwrite
,并且尝试同时打开多个句柄。
示例
基本用法
以下异步事件处理程序函数包含在 Web 工作线程中。其中的代码段创建了一个同步文件访问句柄。
onmessage = async (e) => {
// Retrieve message sent to work from main script
const message = e.data;
// Get handle to draft file
const root = await navigator.storage.getDirectory();
const draftHandle = await root.getFileHandle("draft.txt", { create: true });
// Get sync access handle
const accessHandle = await draftHandle.createSyncAccessHandle();
// …
// Always close FileSystemSyncAccessHandle if done.
accessHandle.close();
};
包含 mode
选项的完整示例
我们的createSyncAccessHandle()
模式测试示例提供了一个<input>
字段用于输入文本,以及两个按钮——一个用于将输入的文本写入来源私有文件系统中的文件末尾,另一个用于在文件变得太满时清空文件。
尝试探索上面的演示,并打开浏览器开发者控制台,以便您可以看到发生了什么。如果您尝试在多个浏览器选项卡中打开演示,您会发现可以同时打开多个句柄以同时写入文件。这是因为在 createSyncAccessHandle()
调用上设置了 mode: "readwrite-unsafe"
。
下面我们将探讨代码。
HTML
<ol>
<li>
<label for="filetext">Enter text to write to the file:</label>
<input type="text" id="filetext" name="filetext" />
</li>
<li>
Write your text to the file: <button class="write">Write text</button>
</li>
<li>
Empty the file if it gets too full:
<button class="empty">Empty file</button>
</li>
</ol>
主要 JavaScript
HTML 文件中的主线程 JavaScript 如下所示。我们获取对写入文本按钮、清空文件按钮和文本输入字段的引用,然后使用 Worker()
构造函数创建一个新的 Web 工作线程。然后,我们定义两个函数并将它们设置为按钮上的事件处理程序
- 单击写入文本按钮时运行
writeToOPFS()
。此函数使用Worker.postMessage()
方法将文本字段的输入值发布到工作线程中的一个对象中,然后清空文本字段,准备进行下一次添加。请注意,传递的对象还包含一个command: "write"
属性,以指定我们希望使用此消息触发写入操作。 - 单击清空文件按钮时运行
emptyOPFS()
。这会将包含command: "empty"
属性的对象发布到工作线程,指定要清空文件。
const writeBtn = document.querySelector(".write");
const emptyBtn = document.querySelector(".empty");
const fileText = document.querySelector("#filetext");
const opfsWorker = new Worker("worker.js");
function writeToOPFS() {
opfsWorker.postMessage({
command: "write",
content: fileText.value,
});
console.log("Main script: Text posted to worker");
fileText.value = "";
}
function emptyOPFS() {
opfsWorker.postMessage({
command: "empty",
});
}
writeBtn.addEventListener("click", writeToOPFS);
emptyBtn.addEventListener("click", emptyOPFS);
工作线程 JavaScript
工作线程 JavaScript 如下所示。
首先,我们运行一个名为 initOPFS()
的函数,该函数使用 StorageManager.getDirectory()
获取对 OPFS 根目录的引用,使用 FileSystemDirectoryHandle.getFileHandle()
创建一个文件并返回其句柄,然后使用 createSyncAccessHandle()
返回一个 FileSystemSyncAccessHandle
。此调用包含 mode: "readwrite-unsafe"
属性,允许多个句柄同时访问同一文件。
let accessHandle;
async function initOPFS() {
const opfsRoot = await navigator.storage.getDirectory();
const fileHandle = await opfsRoot.getFileHandle("file.txt", { create: true });
accessHandle = await fileHandle.createSyncAccessHandle({
mode: "readwrite-unsafe",
});
}
initOPFS();
在工作线程的 消息事件处理程序函数中,我们首先使用 getSize()
获取文件的大小。然后,我们检查消息中发送的数据是否包含 command
属性值为 "empty"
。如果是,我们使用 truncate()
和值为 0
来清空文件,并更新 size
变量中包含的文件大小。
如果消息数据是其他内容,我们将
- 创建一个新的
TextEncoder
和TextDecoder
以便稍后处理文本内容的编码和解码。 - 编码消息数据并将结果写入文件的末尾,使用
write()
,然后更新size
变量中包含的文件大小。 - 创建一个
DataView
来包含文件内容,并使用read()
将内容读取到其中。 - 解码
DataView
内容并将其记录到控制台。
onmessage = function (e) {
console.log("Worker: Message received from main script");
// Get the current size of the file
let size = accessHandle.getSize();
if (e.data.command === "empty") {
// Truncate the file to 0 bytes
accessHandle.truncate(0);
// Get the current size of the file
size = accessHandle.getSize();
} else {
const textEncoder = new TextEncoder();
const textDecoder = new TextDecoder();
// Encode content to write to the file
const content = textEncoder.encode(e.data.content);
// Write the content at the end of the file
accessHandle.write(content, { at: size });
// Get the current size of the file
size = accessHandle.getSize();
// Prepare a data view of the length of the file
const dataView = new DataView(new ArrayBuffer(size));
// Read the entire file into the data view
accessHandle.read(dataView, { at: 0 });
// Log the current file contents to the console
console.log("File contents: " + textDecoder.decode(dataView));
// Flush the changes
accessHandle.flush();
}
// Log the size of the file to the console
console.log("Size: " + size);
};
规范
规范 |
---|
文件系统标准 # api-filesystemfilehandle-createsyncaccesshandle |
浏览器兼容性
BCD 表仅在启用 JavaScript 的浏览器中加载。