FileSystemFileHandle: createSyncAccessHandle()-Methode

Baseline 2023
Newly available

Since March 2023, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.

Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.

Hinweis: Diese Funktion ist nur in Dedicated Web Workers verfügbar.

Die createSyncAccessHandle()-Methode der FileSystemFileHandle-Schnittstelle gibt ein Promise zurück, das zu einem FileSystemSyncAccessHandle-Objekt aufgelöst wird, das verwendet werden kann, um synchron von einer Datei zu lesen und in eine Datei zu schreiben. Die synchrone Natur dieser Methode bietet Leistungsverbesserungen, ist jedoch nur innerhalb dedizierter Web Workers für Dateien innerhalb des Origin Private File System nutzbar.

Das Erstellen eines FileSystemSyncAccessHandle nimmt eine exklusive Sperre auf die Datei, die mit dem Datei-Handle verbunden ist. Dies verhindert die Erstellung weiterer FileSystemSyncAccessHandle oder FileSystemWritableFileStream für die Datei, bis das vorhandene Zugriffs-Handle geschlossen ist.

Syntax

js
createSyncAccessHandle()
createSyncAccessHandle(options)

Parameter

options Optional

Ein Objekt mit den folgenden Eigenschaften:

mode Optional Nicht standardisiert

Ein String, der den Sperrmodus für das Zugriffs-Handle spezifiziert. Der Standardwert ist "readwrite". Mögliche Werte sind:

"read-only"

Mehrere FileSystemSyncAccessHandle-Objekte können gleichzeitig auf einer Datei geöffnet werden (z. B. wenn dieselbe App in mehreren Tabs verwendet wird), solange sie alle im Modus "read-only" geöffnet sind. Sobald geöffnet, können leseähnliche Methoden auf den Handles aufgerufen werden — read(), getSize() und close().

"readwrite"

Es kann nur ein FileSystemSyncAccessHandle-Objekt auf einer Datei geöffnet werden. Der Versuch, weitere Handles zu öffnen, bevor das erste Handle geschlossen ist, führt zu einer NoModificationAllowedError-Exception. Sobald geöffnet, kann jede verfügbare Methode auf dem Handle aufgerufen werden.

"readwrite-unsafe"

Mehrere FileSystemSyncAccessHandle-Objekte können gleichzeitig auf einer Datei geöffnet werden, solange sie alle im Modus "readwrite-unsafe" geöffnet sind. Sobald geöffnet, kann jede verfügbare Methode auf den Handles aufgerufen werden.

Rückgabewert

Ein Promise, das zu einem FileSystemSyncAccessHandle-Objekt aufgelöst wird.

Ausnahmen

NotAllowedError DOMException

Wird ausgelöst, wenn der PermissionStatus.state für das Handle im readwrite-Modus nicht granted ist.

InvalidStateError DOMException

Wird ausgelöst, wenn das FileSystemSyncAccessHandle-Objekt keine Datei im Origin Private File System darstellt.

NotFoundError DOMException

Wird ausgelöst, wenn der aktuelle Eintrag nicht gefunden wird.

NoModificationAllowedError DOMException

Wird ausgelöst, wenn der Browser nicht in der Lage ist, eine Sperre auf die Datei zu setzen, die mit dem Datei-Handle verbunden ist. Dies könnte daran liegen, dass mode auf readwrite gesetzt ist und versucht wird, mehrere Handles gleichzeitig zu öffnen.

Beispiele

Grundlegende Verwendung

Die folgende asynchrone Ereignishandhabungsfunktion befindet sich in einem Web Worker. Der darin enthaltene Codeausschnitt erstellt ein synchrones Datei-Zugriffs-Handle.

js
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();
};

Komplettes Beispiel mit mode-Option

Unser Beispiel für den createSyncAccessHandle() mode test bietet ein <input>-Feld, um Text einzugeben, und zwei Schaltflächen — eine, um den eingegebenen Text am Ende einer Datei im Origin Private File System zu speichern, und eine, um die Datei zu leeren, wenn sie zu voll wird.

Versuchen Sie, das obige Demo zu erkunden, wobei die Entwicklerkonsole des Browsers geöffnet ist, damit Sie sehen können, was passiert. Wenn Sie versuchen, die Demo in mehreren Browser-Tabs zu öffnen, werden Sie feststellen, dass mehrere Handles gleichzeitig geöffnet werden können, um gleichzeitig in die Datei zu schreiben. Dies liegt daran, dass mode: "readwrite-unsafe" auf den createSyncAccessHandle()-Aufrufen gesetzt ist.

Im Folgenden werden wir den Code erkunden.

HTML

Die zwei <button>-Elemente und das Text-<input>-Feld sehen folgendermaßen aus:

html
<ol>
  <li>
    <label for="file-text">Enter text to write to the file:</label>
    <input type="text" id="file-text" name="file-text" />
  </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>

Haupt-JavaScript

Der JavaScript-Code des Haupt-Threads in der HTML-Datei wird unten gezeigt. Wir holen Referenzen zur Schreibtext-Schaltfläche, Leeredatei-Schaltfläche und Text-Eingabefeld, dann erstellen wir einen neuen Web Worker mit dem Worker()-Konstruktor. Wir definieren dann zwei Funktionen und setzen sie als Ereignishandler für die Schaltflächen:

  • writeToOPFS() wird ausgeführt, wenn die Schreibtext-Schaltfläche geklickt wird. Diese Funktion überträgt den eingegebenen Wert des Textfelds an den Worker innerhalb eines Objekts, indem die Methode Worker.postMessage() verwendet wird, und leert dann das Textfeld, um es für die nächste Eingabe vorzubereiten. Beachten Sie, wie das übergebene Objekt auch eine command: "write"-Eigenschaft enthält, um zu spezifizieren, dass wir mit dieser Nachricht eine Schreibaktion auslösen möchten.
  • emptyOPFS() wird ausgeführt, wenn die Leeredatei-Schaltfläche geklickt wird. Dies überträgt ein Objekt mit einer command: "empty"-Eigenschaft an den Worker, das angibt, dass die Datei geleert werden soll.
js
const writeBtn = document.querySelector(".write");
const emptyBtn = document.querySelector(".empty");
const fileText = document.querySelector("#file-text");

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);

Worker-JavaScript

Das Worker-JavaScript wird unten gezeigt.

Zuerst führen wir eine Funktion namens initOPFS() aus, die eine Referenz auf das OPFS-Root-Verzeichnis erhält, indem StorageManager.getDirectory() verwendet wird, eine Datei erstellt und deren Handle zurückgibt, indem FileSystemDirectoryHandle.getFileHandle() verwendet wird, und dann ein FileSystemSyncAccessHandle zurückgibt, indem createSyncAccessHandle() verwendet wird. Dieser Aufruf enthält die Eigenschaft mode: "readwrite-unsafe", die es mehreren Handles ermöglicht, gleichzeitig auf dieselbe Datei zuzugreifen.

js
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();

In der Nachrichten-Ereignishandler-Funktion message event des Workers holen wir zuerst die Größe der Datei, indem getSize() verwendet wird. Dann prüfen wir, ob die Daten, die in der Nachricht gesendet wurden, einen command-Eigenschaftswert von "empty" enthalten. Falls dies so ist, leeren wir die Datei, indem truncate() mit einem Wert von 0 verwendet wird, und aktualisieren die Dateigröße, die in der Variablen size enthalten ist.

Wenn die Nachrichtendaten etwas anderes sind, dann:

  • Erstellen wir einen neuen TextEncoder und TextDecoder, um die Textinhalte später zu kodieren und zu dekodieren.
  • Kodieren wir die Nachrichtendaten und schreiben das Ergebnis an das Ende der Datei, indem write() verwendet wird, dann aktualisieren wir die Dateigröße, die in der Variablen size enthalten ist.
  • Erstellen wir eine DataView, um die Dateiinhalte zu enthalten, und lesen die Inhalte in diese ein, indem read() verwendet wird.
  • Dekodieren wir die DataView-Inhalte und loggen sie in die Konsole.
js
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}`);
};

Spezifikationen

Specification
File System
# api-filesystemfilehandle-createsyncaccesshandle

Browser-Kompatibilität

Siehe auch