Die File System Access API: vereinfachter Zugriff auf lokale Dateien

Mit der File System Access API können Web-Apps Änderungen in Dateien und Ordnern auf dem Gerät des Nutzers direkt lesen oder speichern.

Was ist die File System Access API?

Mit der File System Access API können Entwickler leistungsstarke Web-Apps erstellen, Dateien auf dem lokalen Gerät des Nutzers, z. B. IDEs, Foto- und Video-Editoren, Texteditoren und mehr. Nachher Wenn ein Nutzer einer Webanwendung Zugriff gewährt, können er mit dieser API Änderungen direkt in Dateien lesen oder speichern und Ordner auf dem Gerät des Nutzers. Neben dem Lesen und Schreiben von Dateien bietet die File System Access API die Möglichkeit, ein Verzeichnis zu öffnen und seinen Inhalt aufzulisten.

Wenn Sie bereits mit Lesen und Schreiben von Dateien gearbeitet haben, die Ihnen vertraut sind. Ich empfehle Ihnen, sie trotzdem zu lesen, da nicht alle Systeme gleich sind.

Die File System Access API wird von den meisten Chromium-Browsern auf folgenden Geräten unterstützt: Windows, macOS, ChromeOS und Linux Eine Ausnahme ist Brave, wo derzeit nur hinter einer Kennzeichnung verfügbar. An der Unterstützung für Android wird derzeit im Zusammenhang mit crbug.com/1011535 gearbeitet.

File System Access API verwenden

Um die Leistungsfähigkeit und Nützlichkeit der File System Access API zu demonstrieren, habe ich einen einzelnen Dateitext geschrieben. Editor. Sie können damit eine Textdatei öffnen, bearbeiten, eine neue Datei und speichern Sie die Änderungen auf der Festplatte. Sie ist nichts Besonderes, bietet aber genug, um die Konzepte zu verstehen.

Unterstützte Browser

Unterstützte Browser

  • Chrome: 86 <ph type="x-smartling-placeholder">
  • Edge: 86. <ph type="x-smartling-placeholder">
  • Firefox: nicht unterstützt <ph type="x-smartling-placeholder">
  • Safari: wird nicht unterstützt. <ph type="x-smartling-placeholder">

Quelle

Funktionserkennung

Wenn Sie herausfinden möchten, ob die File System Access API unterstützt wird, prüfen Sie, ob die Auswahlmethode die Sie interessieren, existiert.

if ('showOpenFilePicker' in self) {
  // The `showOpenFilePicker()` method of the File System Access API is supported.
}

Ausprobieren

Die File System Access API in Aktion finden Sie in der Texteditor-Demo

Datei aus dem lokalen Dateisystem lesen

Der erste Anwendungsfall, den ich angehen möchte, besteht darin, die Nutzenden zu bitten, eine Datei auszuwählen, diese dann zu öffnen und zu lesen. von der Festplatte.

Nutzer bitten, eine Datei zum Lesen auszuwählen

Der Einstiegspunkt für die File System Access API ist window.showOpenFilePicker() Wenn er aufgerufen wird, wird ein Dialogfeld für die Dateiauswahl angezeigt, und fordert den Nutzer auf, eine Datei auszuwählen. Nachdem eine Datei ausgewählt wurde, gibt die API ein Array Aliasse. Mit dem optionalen Parameter options können Sie das Verhalten der Dateiauswahl beeinflussen, z. B. indem Sie dem Nutzer die Möglichkeit geben, mehrere Dateien, Verzeichnisse oder unterschiedliche Dateitypen auszuwählen. Wenn keine Optionen angegeben sind, können Nutzer in der Dateiauswahl eine einzelne Datei auswählen. Dies ist ideal für einen Texteditor.

Wie bei vielen anderen leistungsstarken APIs muss showOpenFilePicker() in einer sicheren Umgebung aufgerufen werden. Kontext und muss innerhalb einer Nutzergeste aufgerufen werden.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  // Destructure the one-element array.
  [fileHandle] = await window.showOpenFilePicker();
  // Do something with the file handle.
});

Sobald der Nutzer eine Datei ausgewählt hat, gibt showOpenFilePicker() ein Array mit Handles zurück, in diesem Fall ein Ein-Element-Array mit einem FileSystemFileHandle, der die Eigenschaften und zur Interaktion mit der Datei.

Es ist hilfreich, einen Verweis auf das Datei-Handle beizubehalten, damit es später verwendet werden kann. Es wird die zum Speichern von Änderungen oder anderen Dateivorgängen erforderlich sind.

Datei aus dem Dateisystem lesen

Jetzt, da Sie ein Handle für eine Datei haben, können Sie die Eigenschaften der Datei abrufen oder auf die Datei selbst zugreifen. Ich lese erst mal den Inhalt. Der Aufruf von handle.getFile() gibt ein File zurück. -Objekt, das ein Blob enthält. Rufen Sie zum Abrufen der Daten aus dem Blob einen der zugehörigen Methoden, (slice(), stream(), text() oder arrayBuffer().

const file = await fileHandle.getFile();
const contents = await file.text();

Das von FileSystemFileHandle.getFile() zurückgegebene File-Objekt ist nur lesbar, wenn der die zugrunde liegende Datei auf dem Laufwerk nicht geändert wurde. Wenn die Datei auf dem Laufwerk geändert wird, wird das File-Objekt zu nicht lesbar ist und Sie getFile() noch einmal aufrufen müssen, um ein neues File-Objekt abzurufen, das die geänderten Daten.

Zusammenfassung

Wenn der Nutzer auf die Schaltfläche Öffnen klickt, wird im Browser eine Dateiauswahl angezeigt. Sobald sie eine Datei ausgewählt haben, App liest die Inhalte und fügt sie in ein <textarea> ein.

let fileHandle;
butOpenFile.addEventListener('click', async () => {
  [fileHandle] = await window.showOpenFilePicker();
  const file = await fileHandle.getFile();
  const contents = await file.text();
  textArea.value = contents;
});

Datei in das lokale Dateisystem schreiben

Im Texteditor gibt es zwei Möglichkeiten, eine Datei zu speichern: Speichern und Speichern unter. Speichern schreibt die Änderungen mithilfe des zuvor abgerufenen Datei-Handles in die Originaldatei zurück. Aber speichern As erstellt eine neue Datei und erfordert daher ein neues Datei-Handle.

Neue Datei erstellen

Wenn Sie eine Datei speichern möchten, rufen Sie showSaveFilePicker() auf. Daraufhin wird die Dateiauswahl angezeigt. in „Speichern“ -Modus, in dem der Nutzer eine neue Datei zum Speichern auswählen kann. Für den Text automatisch die Erweiterung .txt hinzufügen, also habe ich Parameter.

async function getNewFileHandle() {
  const options = {
    types: [
      {
        description: 'Text Files',
        accept: {
          'text/plain': ['.txt'],
        },
      },
    ],
  };
  const handle = await window.showSaveFilePicker(options);
  return handle;
}

Änderungen auf dem Laufwerk speichern

Den gesamten Code zum Speichern von Änderungen in einer Datei finden Sie in meiner Texteditor-Demo unter GitHub Die Kerninteraktionen des Dateisystems befinden sich fs-helpers.js Der Vorgang sieht einfach wie der folgende Code aus. Ich werde jeden Schritt durchgehen und erklären.

// fileHandle is an instance of FileSystemFileHandle..
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();
}

Zum Schreiben von Daten auf ein Laufwerk wird ein FileSystemWritableFileStream-Objekt verwendet, eine abgeleitete Klasse von WritableStream. Stream durch Aufrufen von createWritable() für die Datei erstellen Handle-Objekt enthält. Beim Aufruf von createWritable() prüft der Browser zuerst, ob der Nutzer Schreibberechtigung für die Datei. Wenn keine Schreibberechtigung erteilt wurde, fordert der Browser eine um die Berechtigung zu erhalten. Wenn die Berechtigung nicht gewährt wird, gibt createWritable() den Fehler DOMException und die App kann nicht mehr in die Datei schreiben. Im Texteditor gibt die DOMException-Objekte werden in der Methode saveFile() verarbeitet.

Die Methode write() verwendet einen String, der für einen Texteditor benötigt wird. Es kann aber auch eine BufferSource oder ein Blob. Sie können einen Stream beispielsweise direkt an es:

async function writeURLToFile(fileHandle, url) {
  // Create a FileSystemWritableFileStream to write to.
  const writable = await fileHandle.createWritable();
  // Make an HTTP request for the contents.
  const response = await fetch(url);
  // Stream the response into the file.
  await response.body.pipeTo(writable);
  // pipeTo() closes the destination pipe by default, no need to close it.
}

Du kannst auch seek() oder truncate() im Stream verwenden, um die an einer bestimmten Position platzieren oder die Größe der Datei anpassen.

Vorgeschlagenen Dateinamen und Startverzeichnis angeben

In vielen Fällen soll Ihre Anwendung einen Standarddateinamen oder -speicherort vorschlagen. Beispiel: Eine Textanzeige möchte der Editor möglicherweise den Standard-Dateinamen Untitled Text.txt statt Untitled vorschlagen. Ich indem Sie eine suggestedName-Eigenschaft als Teil der showSaveFilePicker-Optionen übergeben.

const fileHandle = await self.showSaveFilePicker({
  suggestedName: 'Untitled Text.txt',
  types: [{
    description: 'Text documents',
    accept: {
      'text/plain': ['.txt'],
    },
  }],
});

Dasselbe gilt für das Standardstartverzeichnis. Wenn Sie einen Texteditor erstellen, das Dialogfeld zum Speichern oder Öffnen von Dateien im Standardordner documents starten, während für ein Bild Editor beginnen, sollten Sie im Standardordner pictures beginnen. Du kannst einen Standardbeginn vorschlagen durch Übergeben einer startIn-Eigenschaft an das showSaveFilePicker-, showDirectoryPicker()- oder showOpenFilePicker-Methoden zu verwenden.

const fileHandle = await self.showOpenFilePicker({
  startIn: 'pictures'
});

Die Liste der bekannten Systemverzeichnisse lautet:

  • desktop: Das Desktopverzeichnis des Nutzers, falls vorhanden.
  • documents: Verzeichnis, in dem vom Nutzer erstellte Dokumente normalerweise gespeichert werden.
  • downloads: Verzeichnis, in dem die heruntergeladenen Dateien normalerweise gespeichert werden
  • music: Verzeichnis, in dem Audiodateien normalerweise gespeichert werden.
  • pictures: Verzeichnis, in dem Fotos und andere Standbilder normalerweise gespeichert werden
  • videos: Verzeichnis, in dem Videos oder Filme normalerweise gespeichert werden.

Neben bekannten Systemverzeichnissen kannst du auch ein vorhandenes Datei- oder Verzeichnis-Handle als einen Wert für startIn Das Dialogfeld wird dann im selben Verzeichnis geöffnet.

// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
  startIn: directoryHandle
});

Zweck verschiedener Dateiauswahlen angeben

Manchmal haben Anwendungen unterschiedliche Auswahlmöglichkeiten für unterschiedliche Zwecke. Zum Beispiel eine Rich-Text- kann der Nutzer Textdateien öffnen und Bilder importieren. Standardmäßig wird jede Datei wird die Auswahl an der zuletzt gemerkten Position geöffnet. Sie können dies umgehen, indem Sie id-Werte speichern für die einzelnen Auswahltypen aus. Wenn ein id angegeben ist, merkt sich die Implementierung der Dateiauswahl einen separates zuletzt verwendetes Verzeichnis für diese id.

const fileHandle1 = await self.showSaveFilePicker({
  id: 'openText',
});

const fileHandle2 = await self.showSaveFilePicker({
  id: 'importImage',
});

Datei- oder Verzeichnis-Handles in IndexedDB speichern

Datei- und Verzeichnis-Handles sind serialisierbar, d. h., Sie können eine Datei oder Verzeichnis-Handle an IndexedDB an oder rufen Sie postMessage() auf, um sie zwischen derselben obersten Ebene Ursprung.

Wenn Sie Datei- oder Verzeichnis-Handles in IndexedDB speichern, können Sie den Status speichern oder sich merken, oder Verzeichnisse, an denen ein Nutzer arbeitete. So können Sie eine Liste der zuletzt geöffneten oder bearbeitete Dateien, erneut das Öffnen der letzten Datei anbieten, wenn die App geöffnet wird, die vorherige Bearbeitung wiederherstellen Verzeichnis und mehr. Im Texteditor speichere ich eine Liste der fünf letzten Dateien des Nutzers. sodass Sie wieder auf diese Dateien zugreifen können.

Das folgende Codebeispiel zeigt, wie ein Datei- und ein Verzeichnis-Handle gespeichert und abgerufen werden können. Sie können in der Praxis in Glitch sehen. (Ich verwende der Einfachheit halber die Bibliothek idb-keyval.)

import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';

const pre1 = document.querySelector('pre.file');
const pre2 = document.querySelector('pre.directory');
const button1 = document.querySelector('button.file');
const button2 = document.querySelector('button.directory');

// File handle
button1.addEventListener('click', async () => {
  try {
    const fileHandleOrUndefined = await get('file');
    if (fileHandleOrUndefined) {
      pre1.textContent = `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const [fileHandle] = await window.showOpenFilePicker();
    await set('file', fileHandle);
    pre1.textContent = `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

// Directory handle
button2.addEventListener('click', async () => {
  try {
    const directoryHandleOrUndefined = await get('directory');
    if (directoryHandleOrUndefined) {
      pre2.textContent = `Retrieved directroy handle "${directoryHandleOrUndefined.name}" from IndexedDB.`;
      return;
    }
    const directoryHandle = await window.showDirectoryPicker();
    await set('directory', directoryHandle);
    pre2.textContent = `Stored directory handle for "${directoryHandle.name}" in IndexedDB.`;
  } catch (error) {
    alert(error.name, error.message);
  }
});

Handles und Berechtigungen für gespeicherte Dateien oder Verzeichnisse

Da Berechtigungen zwischen Sitzungen nicht immer beibehalten werden, sollten Sie überprüfen, ob der Nutzer hat mithilfe von queryPermission() die Berechtigung für die Datei oder das Verzeichnis erteilt. Ist dies nicht der Fall, requestPermission(), um sie (noch einmal) anzufordern. Dies funktioniert auf die gleiche Weise für Datei- und Verzeichnis-Handles. Ich fileOrDirectoryHandle.requestPermission(descriptor) ausführen oder fileOrDirectoryHandle.queryPermission(descriptor).

Im Texteditor habe ich eine verifyPermission()-Methode erstellt, die prüft, ob der Nutzer erteilt und bei Bedarf die Anfrage stellt.

async function verifyPermission(fileHandle, readWrite) {
  const options = {};
  if (readWrite) {
    options.mode = 'readwrite';
  }
  // Check if permission was already granted. If so, return true.
  if ((await fileHandle.queryPermission(options)) === 'granted') {
    return true;
  }
  // Request permission. If the user grants permission, return true.
  if ((await fileHandle.requestPermission(options)) === 'granted') {
    return true;
  }
  // The user didn't grant permission, so return false.
  return false;
}

Indem ich mit der Leseanfrage eine Schreibberechtigung angefordert habe, habe ich die Anzahl der Berechtigungsaufforderungen reduziert. Der Nutzer sieht beim Öffnen der Datei eine Aufforderung und erteilt die Berechtigung zum Lesen und Schreiben der Datei.

Verzeichnis öffnen und Inhalt auflisten

Rufen Sie zum Auflisten aller Dateien in einem Verzeichnis showDirectoryPicker() auf. Der Nutzer Wählt ein Verzeichnis in einer Auswahl aus, danach wird ein FileSystemDirectoryHandle zurückgegeben, mit dem Sie die Dateien des Verzeichnisses aufzählen und darauf zugreifen können. In der Standardeinstellung sehen Sie Zugriff auf die Dateien im Verzeichnis haben. Wenn Sie jedoch Schreibzugriff benötigen, können Sie { mode: 'readwrite' } hinzu.

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  for await (const entry of dirHandle.values()) {
    console.log(entry.kind, entry.name);
  }
});

Wenn Sie zusätzlich mit getFile() auf jede Datei zugreifen müssen, z. B. um die Person abzurufen, nicht für jedes Ergebnis nacheinander await verwenden, sondern alle Dateien in parallel, z. B. mit Promise.all().

butDir.addEventListener('click', async () => {
  const dirHandle = await window.showDirectoryPicker();
  const promises = [];
  for await (const entry of dirHandle.values()) {
    if (entry.kind !== 'file') {
      continue;
    }
    promises.push(entry.getFile().then((file) => `${file.name} (${file.size})`));
  }
  console.log(await Promise.all(promises));
});

Dateien und Ordner in einem Verzeichnis erstellen oder darauf zugreifen

Von einem Verzeichnis aus können Sie Dateien und Ordner mithilfe der getFileHandle() bzw. getDirectoryHandle() . Durch Übergabe eines optionalen options-Objekts mit dem Schlüssel create und dem booleschen Wert Mit true oder false können Sie festlegen, ob eine neue Datei oder ein neuer Ordner erstellt werden soll, falls noch nicht vorhanden.

// In an existing directory, create a new directory named "My Documents".
const newDirectoryHandle = await existingDirectoryHandle.getDirectoryHandle('My Documents', {
  create: true,
});
// In this new directory, create a file named "My Notes.txt".
const newFileHandle = await newDirectoryHandle.getFileHandle('My Notes.txt', { create: true });

Pfad eines Elements in einem Verzeichnis auflösen

Wenn Sie mit Dateien oder Ordnern in einem Verzeichnis arbeiten, kann es hilfreich sein, den Pfad des Elements aufzulösen betroffene Website. Dazu können Sie die Methode resolve() mit dem passenden Namen verwenden. Zur Lösung Das Element kann ein direktes oder indirektes untergeordnetes Element des Verzeichnisses sein.

// Resolve the path of the previously created file called "My Notes.txt".
const path = await newDirectoryHandle.resolve(newFileHandle);
// `path` is now ["My Documents", "My Notes.txt"]

Dateien und Ordner in einem Verzeichnis löschen

Wenn Sie Zugriff auf ein Verzeichnis erhalten haben, können Sie die enthaltenen Dateien und Ordner mit der Funktion removeEntry()-Methode. Bei Ordnern kann das Löschen optional rekursiv sein und Folgendes beinhalten: Unterordner und die darin enthaltenen Dateien.

// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });

Dateien oder Ordner direkt löschen

Wenn du Zugriff auf einen Datei- oder Verzeichnis-Handle hast, rufe remove() auf einem FileSystemFileHandle- oder FileSystemDirectoryHandle, um sie zu entfernen.

// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();

Dateien und Ordner umbenennen und verschieben

Sie können Dateien und Ordner umbenennen oder an einen neuen Speicherort verschieben. Rufen Sie dazu move() auf der FileSystemHandle-Schnittstelle. FileSystemHandle hat die untergeordneten Oberflächen FileSystemFileHandle und FileSystemDirectoryHandle Die Methode move() verwendet einen oder zwei Parameter. Die erste kann entweder ein String mit dem neuen Namen oder ein FileSystemDirectoryHandle in den Zielordner sein. Im In letzterem Fall ist der optionale zweite Parameter ein String mit dem neuen Namen, sodass das Verschieben und Umbenennen in einem Schritt erfolgen.

// Rename the file.
await file.move('new_name');
// Move the file to a new directory.
await file.move(directory);
// Move the file to a new directory and rename it.
await file.move(directory, 'newer_name');

Drag-and-drop-Integration

Die HTML-Drag-and-drop-Oberflächen Web-Anwendungen zu ermöglichen, per Drag-and-drop verschoben auf einer Webseite. Während eines Drag-and-drop-Vorgangs werden per Drag-and-drop eingefügte Datei- und Verzeichniselemente verknüpft mit Datei- bzw. Verzeichniseinträgen. Das DataTransferItem.getAsFileSystemHandle() -Methode gibt ein Promise mit einem FileSystemFileHandle-Objekt zurück, wenn das gezogene Element eine Datei ist, und ein Versprechen mit einem FileSystemDirectoryHandle-Objekt, wenn das per Drag-and-drop verschobene Element ein Verzeichnis ist. Der folgende Eintrag zeigt dies in der Praxis. Die Funktion DataTransferItem.kind ist "file" für Dateien und Verzeichnisse, während FileSystemHandle.kind der File System Access API "file" für Dateien und "directory" für Verzeichnisse.

elem.addEventListener('dragover', (e) => {
  // Prevent navigation.
  e.preventDefault();
});

elem.addEventListener('drop', async (e) => {
  e.preventDefault();

  const fileHandlesPromises = [...e.dataTransfer.items]
    .filter((item) => item.kind === 'file')
    .map((item) => item.getAsFileSystemHandle());

  for await (const handle of fileHandlesPromises) {
    if (handle.kind === 'directory') {
      console.log(`Directory: ${handle.name}`);
    } else {
      console.log(`File: ${handle.name}`);
    }
  }
});

Auf das private Ursprungsdateisystem zugreifen

Das private Ursprungsdateisystem ist ein Speicherendpunkt, der, wie der Name schon sagt, für die den Ursprung der Seite. Browser implementieren dies in der Regel, indem sie den Inhalt dieses auf der Festplatte gespeichert werden soll, ist es nicht beabsichtigt, zugänglich zu machen. Ebenso wird nicht erwartet, dass Dateien oder Verzeichnisse, deren Namen mit dem Namen von untergeordneten Elementen des privaten Dateisystems des Ursprungs vorhanden sind. Auch wenn der Browser den Eindruck erweckt, Da es sich um ein privates Dateisystem des Ursprungs handelt, kann der Browser intern Dateien speichern. diese „Dateien“ in einer Datenbank oder einer anderen Datenstruktur gespeichert werden. Wenn Sie diese API verwenden, erwarten nicht, dass sie genau die erstellten Dateien auf der Festplatte finden. Sie können wie gewohnt arbeiten auf das private Ursprungsdateisystem, sobald Sie Zugriff auf das Stammverzeichnis FileSystemDirectoryHandle haben.

const root = await navigator.storage.getDirectory();
// Create a new file handle.
const fileHandle = await root.getFileHandle('Untitled.txt', { create: true });
// Create a new directory handle.
const dirHandle = await root.getDirectoryHandle('New Folder', { create: true });
// Recursively remove a directory.
await root.removeEntry('Old Stuff', { recursive: true });

Unterstützte Browser

  • Chrome: 86 <ph type="x-smartling-placeholder">
  • Edge: 86. <ph type="x-smartling-placeholder">
  • Firefox: 111 <ph type="x-smartling-placeholder">
  • Safari: 15.2 <ph type="x-smartling-placeholder">

Quelle

Zugriff auf leistungsoptimierte Dateien über das private Dateisystem des Ursprungs

Das private Ursprungsdateisystem bietet optionalen Zugriff auf eine spezielle Art von Datei, die sehr wichtig ist, leistungsoptimiert, indem beispielsweise direkter und exklusiver Schreibzugriff auf die Datei Inhalte. In Chromium 102 und höher gibt es im privaten Ursprungsdateisystem eine zusätzliche Methode für Vereinfachung des Dateizugriffs: createSyncAccessHandle() (für synchrone Lese- und Schreibvorgänge). Erscheint am FileSystemFileHandle, aber ausschließlich in Web Worker.

// (Read and write operations are synchronous,
// but obtaining the handle is asynchronous.)
// Synchronous access exclusively in Worker contexts.
const accessHandle = await fileHandle.createSyncAccessHandle();
const writtenBytes = accessHandle.write(buffer);
const readBytes = accessHandle.read(buffer, { at: 1 });

Polyfilling

Es ist nicht möglich, die File System Access API-Methoden vollständig mit Polyfill zu füllen.

  • Die Methode showOpenFilePicker() kann mit einem <input type="file">-Element angenähert werden.
  • Die Methode showSaveFilePicker() kann mit einem <a download="file_name">-Element simuliert werden. allerdings löst dies einen programmatischen Download aus und ermöglicht das Überschreiben vorhandener Dateien nicht.
  • Die Methode showDirectoryPicker() kann mit der nicht standardmäßigen <input type="file" webkitdirectory>-Element.

Wir haben dazu eine Bibliothek namens browser-fs-access entwickelt, die die Datei System Access API nach Möglichkeit. Das ist die nächstbeste Option in allen anderen Cases.

Sicherheit und Berechtigungen

Das Chrome-Team hat die File System Access API nach den Grundprinzipien entwickelt und implementiert. wie unter Zugriff auf leistungsstarke Webplattform-Funktionen steuern beschrieben, einschließlich Transparenz und Ergonomie.

Datei öffnen oder neue Datei speichern

<ph type="x-smartling-placeholder">
</ph> Dateiauswahl zum Öffnen einer Datei zum Lesen <ph type="x-smartling-placeholder">
</ph> Dateiauswahl, mit der eine vorhandene Datei zum Lesen geöffnet wird.

Beim Öffnen einer Datei gibt der Nutzer mithilfe der Dateiauswahl die Berechtigung zum Lesen einer Datei oder eines Verzeichnisses an. Die Dateiauswahl kann nur dann mit einer Nutzergeste angezeigt werden, wenn sie über eine sichere Kontext. Wenn Nutzer ihre Meinung ändern, können sie die Auswahl in der Datei abbrechen. und die Website hat keinen Zugriff. Dies ist dasselbe Verhalten wie bei der <input type="file">-Element.

<ph type="x-smartling-placeholder">
</ph> Dateiauswahl zum Speichern einer Datei auf der Festplatte <ph type="x-smartling-placeholder">
</ph> Dateiauswahl zum Speichern einer Datei auf der Festplatte

Wenn eine Webanwendung eine neue Datei speichern möchte, zeigt der Browser die Auswahl zum Speichern von Dateien an. Nutzer können den Namen und den Speicherort der neuen Datei angeben. Da sie gerade eine neue Datei (im Gegensatz zum Überschreiben einer vorhandenen Datei) gewährt die Dateiauswahl der App die Berechtigung, in die Datei schreiben.

Eingeschränkte Ordner

Um Nutzer und deren Daten zu schützen, kann der Browser die Speichermöglichkeiten des Nutzers auf bestimmte z. B. wichtige Betriebssystemordner wie Windows oder die macOS-Bibliotheksordner. In diesem Fall wird im Browser eine Aufforderung angezeigt, in der der Nutzer aufgefordert wird, eine andere Ordner.

Vorhandene Datei oder Verzeichnis ändern

Eine Web-App kann eine Datei auf der Festplatte nicht ohne ausdrückliche Genehmigung des Nutzers ändern.

Berechtigungsaufforderung

Wenn eine Person Änderungen an einer Datei speichern möchte, auf die sie zuvor Lesezugriff gewährt hat, kann der Browser zeigt eine Berechtigungsaufforderung an, mit der die Website um die Berechtigung zum Schreiben von Änderungen auf die Festplatte gebeten wird. Die Berechtigungsanfrage kann nur durch eine Nutzergeste ausgelöst werden, z. B. durch Klicken auf Schaltfläche.

<ph type="x-smartling-placeholder">
</ph> Berechtigungsaufforderung, die vor dem Speichern einer Datei angezeigt wird. <ph type="x-smartling-placeholder">
</ph> Aufforderung, die Nutzern angezeigt wird, bevor dem Browser ein Schreibvorgang gewährt wird Berechtigung für eine vorhandene Datei.

Alternativ kann eine Web-App, die mehrere Dateien bearbeitet, z. B. eine IDE, auch nach der Berechtigung zum Speichern fragen zum Zeitpunkt der Eröffnung ändert.

Wenn der Nutzer „Abbrechen“ auswählt und keinen Schreibzugriff gewährt, kann die Webanwendung keine Änderungen an der lokale Datei. Es sollte den Nutzenden eine alternative Methode zum Speichern ihrer Daten bieten, z. B. indem sie eine Möglichkeit bieten, „herunterzuladen“, oder Daten in der Cloud speichern.

Transparenz

<ph type="x-smartling-placeholder">
</ph> Omnibox-Symbol <ph type="x-smartling-placeholder">
</ph> Symbol in der Adressleiste, das anzeigt, dass der Nutzer der Website die Berechtigung erteilt hat in einer lokalen Datei speichern.

Sobald ein Nutzer einer Webanwendung die Berechtigung zum Speichern einer lokalen Datei erteilt hat, wird im Browser ein Symbol angezeigt. in die Adressleiste ein. Wenn Sie auf das Symbol klicken, wird ein Pop-over mit der Liste der Dateien geöffnet, die der Nutzer angegeben hat. auf die Sie zugreifen können. Der Nutzer kann diesen Zugriff jederzeit widerrufen.

Berechtigungstreue

Die Web-App kann so lange Änderungen an der Datei speichern, bis alle Tabs für ihre Ursprung geschlossen. Sobald ein Tab geschlossen wird, verliert die Website den Zugriff auf die Website. Wenn die Nutzenden das nächste Mal Web-App verwenden, werden sie noch einmal zum Zugriff auf die Dateien aufgefordert.

Feedback

Wir würden gern wissen, welche Erfahrungen du mit der File System Access API gemacht hast.

Informationen zum API-Design

Funktioniert die API nicht wie erwartet? Oder fehlen Methoden, oder Eigenschaften, die Sie für die Umsetzung Ihrer Idee benötigen? Fragen oder Kommentare zur Sicherheit haben Modell?

Probleme bei der Implementierung?

Haben Sie bei der Implementierung von Chrome einen Fehler gefunden? Oder weicht die Implementierung von der Spezifikation ab?

  • Melden Sie den Fehler unter https://new.crbug.com. Geben Sie so viele Details wie möglich an, für die Reproduktion und stelle Komponenten auf Blink>Storage>FileSystem ein. Glitch eignet sich hervorragend, um schnelle Reproduzierungen zu teilen.

Möchten Sie die API verwenden?

Möchten Sie die File System Access API auf Ihrer Website verwenden? Ihre öffentliche Unterstützung hilft uns, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.

Nützliche Links

Danksagungen

Die Spezifikation für das File System Access API wurde geschrieben von Marijn Kruisselbrink