API File System Access: semplifica l'accesso ai file locali

L'API Accesso al file system consente alle app web di leggere o salvare le modifiche direttamente in file e cartelle sul dispositivo dell'utente.

L'API File System Access consente agli sviluppatori di creare potenti app web che interagiscono con i file sul dispositivo locale dell'utente, ad esempio IDE, editor di foto e video, editor di testo e altro ancora. Dopo che un utente ha concesso l'accesso a un'app web, questa API gli consente di leggere o salvare le modifiche direttamente nei file e nelle cartelle sul suo dispositivo. Oltre a leggere e scrivere file, l'API Accesso al file system offre la possibilità di aprire una directory ed enumerarne i contenuti.

Se hai già lavorato con la lettura e la scrittura di file, gran parte di ciò che sto per condividere ti sarà familiare. Ti invitiamo a leggerlo comunque, perché non tutti i sistemi sono uguali.

L'API File System Access è supportata sulla maggior parte dei browser Chromium su Windows, macOS, ChromeOS e Linux. Un'eccezione degna di nota è Brave, dove attualmente è disponibile solo dietro segnalazione. L'assistenza per Android è in fase di sviluppo nel contesto di crbug.com/1011535.

Utilizzo dell'API File System Access

Per mostrare la potenza e l'utilità dell'API Accesso al file system, ho scritto un singolo editor di testo per file. Ti consente di aprire un file di testo, modificarlo, salvare le modifiche sul disco o avviare un nuovo file e salvare le modifiche sul disco. Non è niente di speciale, ma fornisce informazioni sufficienti per aiutarti a comprendere i concetti.

Supporto browser

Supporto dei browser

  • Chrome: 86.
  • Edge: 86.
  • Firefox: non supportato.
  • Safari: non supportato.

Origine

Rilevamento delle caratteristiche

Per scoprire se l'API Accesso al file system è supportata, controlla se esiste il metodo di selettore che ti interessa.

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

Prova

Guarda l'API File System Access in azione nella demo dell'editor di testo.

Leggere un file dal file system locale

Il primo caso d'uso che voglio affrontare è chiedere all'utente di scegliere un file, quindi aprirlo e leggerlo dal disco.

Chiedi all'utente di scegliere un file da leggere

Il punto di contatto dell'API File System Access è window.showOpenFilePicker(). Quando viene chiamato, mostra una finestra di dialogo di selezione dei file e chiede all'utente di selezionarne uno. Dopo aver selezionato un file, l'API restituisce un array di handle di file. Un parametro options facoltativo ti consente di influenzare il comportamento del selettore di file, ad esempio consentendo all'utente di selezionare più file, directory o tipi di file diversi. Senza opzioni specificate, il selettore di file consente all'utente di selezionare un singolo file. È ideale per un editor di testo.

Come molte altre API efficaci, la chiamata a showOpenFilePicker() deve essere eseguita in un contesto sicuro e deve essere chiamata all'interno di un gesto dell'utente.

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

Una volta che l'utente ha selezionato un file, showOpenFilePicker() restituisce un array di handle, in questo caso un array di un solo elemento con un elemento FileSystemFileHandle contenente le proprietà e i metodi necessari per interagire con il file.

È utile conservare un riferimento all'handle del file in modo da poterlo utilizzare in un secondo momento. Sarà necessario salvare le modifiche al file o eseguire altre operazioni sui file.

Leggere un file dal file system

Ora che hai un handle per un file, puoi recuperare le proprietà del file o accedere al file stesso. Per il momento, ne leggerò il contenuto. La chiamata a handle.getFile() restituisce un oggetto File contenente un blob. Per recuperare i dati dal blob, chiama uno dei metodi (slice(), stream(), text() o arrayBuffer()).

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

L'oggetto File restituito da FileSystemFileHandle.getFile() è leggibile solo se il file di base sul disco non è cambiato. Se il file sul disco viene modificato, l'oggetto File diventa illeggibile e dovrai chiamare di nuovo getFile() per ottenere un nuovo oggetto File che legga i dati modificati.

Riassumendo

Quando gli utenti fanno clic sul pulsante Apri, il browser mostra un selettore di file. Dopo aver selezionato un file, l'app ne legge i contenuti e li inserisce in un <textarea>.

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

Scrivere il file nel file system locale

Nell'editor di testo, esistono due modi per salvare un file: Salva e Salva con nome. Salva riapplica le modifiche al file originale utilizzando l'handle del file recuperato in precedenza. Tuttavia, Salva come crea un nuovo file e richiede quindi un nuovo handle file.

Crea un nuovo file

Per salvare un file, chiama showSaveFilePicker(), che mostra il selettore di file in modalità "Salva", consentendo all'utente di scegliere un nuovo file da utilizzare per il salvataggio. Per l'editor di testo, volevo anche che aggiungesse automaticamente un'estensione .txt, quindi ho fornito alcuni parametri aggiuntivi.

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

Salva le modifiche sul disco

Puoi trovare tutto il codice per salvare le modifiche in un file nella mia demo dell'editor di testo su GitHub. Le interazioni di base con il file system si trovano in fs-helpers.js. Nella sua forma più semplice, il processo è simile al seguente codice. Ti illustrerò ogni passaggio.

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

La scrittura dei dati sul disco utilizza un oggetto FileSystemWritableFileStream, una sottoclasse di WritableStream. Crea lo stream chiamando createWritable() sull'oggetto handle del file. Quando viene chiamato createWritable(), il browser controlla prima se l'utente ha concesso l'autorizzazione di scrittura al file. Se l'autorizzazione di scrittura non è stata concessa, il browser chiede all'utente di autorizzarla. Se l'autorizzazione non viene concessa, createWritable() lancia un DOMException e l'app non potrà scrivere nel file. Nell'editor di testo, gli oggetti DOMException vengono gestiti nel metodo saveFile().

Il metodo write() accetta una stringa, che è ciò che serve per un editor di testo. ma può anche accettare un BufferSource o un Blob. Ad esempio, puoi incanalare uno stream direttamente in esso:

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.
}

Puoi anche utilizzare seek() o truncate() all'interno dello stream per aggiornare il file in una posizione specifica o ridimensionarlo.

Specifica un nome file e una directory di partenza suggeriti

In molti casi potresti volere che la tua app suggerisca un nome o una posizione predefiniti per il file. Ad esempio, un editor di testo potrebbe suggerire un nome file predefinito Untitled Text.txt anziché Untitled. Puoi farlo passando una proprietà suggestedName come parte delle opzioni showSaveFilePicker.

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

Lo stesso vale per la home directory predefinita. Se stai creando un editor di testo, ti consigliamo di avviare la finestra di dialogo di salvataggio o apertura del file nella cartella documents predefinita, mentre per un editor di immagini ti consigliamo di avviare la finestra di dialogo nella cartella documents predefinita.pictures Puoi suggerire una directory iniziale predefinita passando una proprietà startIn ai metodi showSaveFilePicker, showDirectoryPicker() o showOpenFilePicker, ad esempio in questo modo.

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

L'elenco di directory di sistema note è:

  • desktop: la directory del computer dell'utente, se esistente.
  • documents: directory in cui vengono generalmente archiviati i documenti creati dall'utente.
  • downloads: la directory in cui in genere vengono archiviati i file scaricati.
  • music: directory in cui vengono generalmente archiviati i file audio.
  • pictures: la directory in cui in genere vengono memorizzate le foto e altre immagini fisse.
  • videos: la directory in cui in genere vengono archiviati i video o i film.

Oltre alle directory di sistema ben note, puoi anche passare un handle di file o directory esistente come valore per startIn. La finestra di dialogo si aprirà nella stessa directory.

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

Specificare lo scopo di diversi selettori di file

A volte le applicazioni hanno selettori diversi per scopi diversi. Ad esempio, un editor di testo avanzato può consentire all'utente di aprire file di testo, ma anche di importare immagini. Per impostazione predefinita, ogni visualizzatore di file si apre nell'ultima posizione memorizzata. Puoi aggirare il problema memorizzando i valori id per ogni tipo di selettore. Se viene specificato un id, l'implementazione del selettore di file memorizza una directory di ultima utilizzo distinta per quel id.

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

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

Memorizzazione di handle di file o directory in IndexedDB

Gli handle di file e di directory sono serializzabili, il che significa che puoi salvare un handle di file o directory in IndexedDB oppure chiamare postMessage() per inviarli tra la stessa origine di primo livello.

Se salvi gli handle di file o directory in IndexedDB, puoi memorizzare lo stato o ricordare su quali file o directory un utente stava lavorando. In questo modo è possibile mantenere un elenco dei file aperti o modificati di recente, offrire la possibilità di riaprire l'ultimo file quando l'app viene aperta, ripristinare la directory di lavoro precedente e altro ancora. Nell'editor di testo, memorizzo un elenco dei cinque file più recenti aperti dall'utente, consentendo di accedervi di nuovo.

Il seguente esempio di codice mostra la memorizzazione e il recupero di un handle file e di un handle directory. Puoi guardare come funziona su Glitch. Per brevità, utilizzo la libreria 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);
  }
});

Handle e autorizzazioni di file o directory archiviati

Poiché le autorizzazioni non vengono sempre mantenute tra le sessioni, devi verificare se l'utente ha concesso l'autorizzazione al file o alla directory utilizzando queryPermission(). In caso contrario, chiama requestPermission() per (richiedere di) ottenerne uno. Lo stesso vale per gli handle di file e directory. Devi eseguire fileOrDirectoryHandle.requestPermission(descriptor) o fileOrDirectoryHandle.queryPermission(descriptor) rispettivamente.

Nell'editor di testo ho creato un metodo verifyPermission() che verifica se l'utente ha già concesso l'autorizzazione e, se necessario, effettua la richiesta.

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

Richiedendo l'autorizzazione di scrittura con la richiesta di lettura, ho ridotto il numero di richieste di autorizzazione. L'utente vede una richiesta quando apre il file e concede l'autorizzazione sia in lettura che in scrittura.

Apertura di una directory ed enumerazione dei relativi contenuti

Per enumerare tutti i file di una directory, chiama showDirectoryPicker(). L'utente selezione una directory in un selettore, dopodiché viene restituito un FileSystemDirectoryHandle che consente di enumerare e accedere ai file della directory. Per impostazione predefinita, avrai accesso in lettura ai file nella directory, ma se hai bisogno di accesso in scrittura, puoi passare { mode: 'readwrite' } al metodo.

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

Se devi anche accedere a ogni file utilizzando getFile() per, ad esempio, ottenere le dimensioni dei singoli file, non utilizzare await su ogni risultato in sequenza, ma elabora tutti i file in parallelo, ad esempio utilizzando 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));
});

Creazione o accesso a file e cartelle in una directory

Da una directory, puoi creare o accedere a file e cartelle utilizzando il metodo getFileHandle() o getDirectoryHandle(). Se passi un oggetto options facoltativo con una chiave create e un valore booleano true o false, puoi determinare se deve essere creato un nuovo file o una nuova cartella se non esistono.

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

Risoluzione del percorso di un elemento in una directory

Quando lavori con file o cartelle in una directory, può essere utile risolvere il percorso dell'elemento in questione. Questa operazione può essere eseguita con il metodo resolve(), dal nome appropriato. Per la risoluzione, l'elemento può essere un elemento secondario diretto o indiretto della directory.

// 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"]

Eliminare file e cartelle in una directory

Se hai ottenuto l'accesso a una directory, puoi eliminare i file e le cartelle contenuti con il metodo removeEntry(). Per le cartelle, l'eliminazione può essere facoltativamente ricorsiva e includere tutte le sottocartelle e i file al loro interno.

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

Eliminazione diretta di un file o di una cartella

Se hai accesso a un handle di file o directory, chiama remove() su un FileSystemFileHandle o FileSystemDirectoryHandle per rimuoverlo.

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

Rinominare e spostare file e cartelle

I file e le cartelle possono essere rinominati o spostati in una nuova posizione chiamando move() nell'interfaccia FileSystemHandle. FileSystemHandle ha le interfacce secondarie FileSystemFileHandle e FileSystemDirectoryHandle. Il metodo move() richiede uno o due parametri. Il primo può essere una stringa con il nuovo nome o un FileSystemDirectoryHandle alla cartella di destinazione. Nel secondo caso, il secondo parametro facoltativo è una stringa con il nuovo nome, quindi è possibile spostarli e rinominarli in un solo passaggio.

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

Integrazione con la funzionalità di trascinamento

Le interfacce HTML Drag and Drop consentono alle applicazioni web di accettare file trascinati in una pagina web. Durante un'operazione di trascinamento, gli elementi di file e directory trascinati vengono associati rispettivamente alle voci di file e alle voci di directory. Il metodo DataTransferItem.getAsFileSystemHandle() restituisce una promessa con un oggetto FileSystemFileHandle se l'elemento trascinato è un file e una promessa con un oggetto FileSystemDirectoryHandle se l'elemento trascinato è una directory. La seguente scheda lo mostra in azione. Tieni presente che DataTransferItem.kind dell'interfaccia di trascinamento è "file" sia per i file che per le directory, mentre FileSystemHandle.kind dell'API File System Access è "file" per i file e "directory" per le directory.

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

Accesso al file system privato di origine

Il file system privato di origine è un endpoint di archiviazione che, come suggerisce il nome, è privato per l'origine della pagina. Sebbene i browser in genere lo implementino, memorizzando i contenuti di questo file system privato di origine su disco da qualche parte, non è previsto che i contenuti siano accessibili all'utente. Analogamente, non è previsto che esistano file o directory con nomi corrispondenti ai nomi delle directory secondarie del file system privato di origine. Sebbene il browser possa far sembrare che ci siano file, internamente, poiché si tratta di un file system privato dell'origine, il browser potrebbe memorizzare questi "file" in un database o in qualsiasi altra struttura di dati. In sostanza, se utilizzi questa API, non aspettarti di trovare i file creati in corrispondenza uno a uno da qualche parte sull'hard disk. Una volta ottenuto l'accesso alla radice FileSystemDirectoryHandle, puoi operare come al solito sul file system privato di origine.

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

Supporto dei browser

  • Chrome: 86.
  • Edge: 86.
  • Firefox: 111.
  • Safari: 15.2.

Origine

Accesso ai file ottimizzati per le prestazioni dal file system privato di origine

Il file system privato di origine fornisce l'accesso facoltativo a un tipo speciale di file altamente ottimizzato per le prestazioni, ad esempio offrendo l'accesso in scrittura in-place ed esclusivo ai contenuti di un file. In Chromium 102 e versioni successive, è disponibile un metodo aggiuntivo nel file system privato di origine per semplificare l'accesso ai file: createSyncAccessHandle() (per operazioni di lettura e scrittura sincrone). È esposta su FileSystemFileHandle, ma esclusivamente in Web Workers.

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

Riempimento

Non è possibile eseguire il polyfill completo dei metodi dell'API File System Access.

  • Il metodo showOpenFilePicker() può essere approssimato con un elemento <input type="file">.
  • Il metodo showSaveFilePicker() può essere simulato con un elemento <a download="file_name">, anche se questo attiva un download programmatico e non consente di sovrascrivere i file esistenti.
  • Il metodo showDirectoryPicker() può essere in qualche modo emulato con l'elemento <input type="file" webkitdirectory> non standard.

Abbiamo sviluppato una libreria chiamata browser-fs-access che utilizza l'API File System Access, ove possibile, e passa a queste opzioni di riserva in tutti gli altri casi.

Sicurezza e autorizzazioni

Il team di Chrome ha progettato e implementato l'API File System Access utilizzando i principi fondamentali definiti in Controllo dell'accesso a funzionalità potenti della piattaforma web, tra cui il controllo e la trasparenza per gli utenti, nonché l'ergonomia utente.

Apertura di un file o salvataggio di un nuovo file

Selettore file per aprire un file per la lettura
Un selettore di file utilizzato per aprire un file esistente per la lettura.

Quando apre un file, l'utente fornisce l'autorizzazione per leggere un file o una directory utilizzando il selettore di file. Il selettore di file aperti può essere mostrato solo utilizzando un gesto dell'utente quando viene visualizzato da un contesto sicuro. Se gli utenti cambiano idea, possono annullare la selezione nel selettore di file e il sito non avrà accesso a nulla. Si tratta dello stesso comportamento dell'elemento <input type="file">.

Selettore di file per salvare un file sul disco.
Un selettore di file utilizzato per salvare un file sul disco.

Analogamente, quando un'app web vuole salvare un nuovo file, il browser mostra il selettore per il salvataggio del file, consentendo all'utente di specificare il nome e la posizione del nuovo file. Poiché sta salvando un nuovo file sul dispositivo (anziché sovrascrivere un file esistente), il selettore file concede all'app l'autorizzazione a scrivere nel file.

Cartelle con limitazioni

Per proteggere gli utenti e i loro dati, il browser potrebbe limitare la possibilità di salvare in determinate cartelle, ad esempio le cartelle di sistema operativo di base come Windows e le cartelle Libreria di macOS. In questo caso, il browser mostra una richiesta e chiede all'utente di scegliere un'altra cartella.

Modificare un file o una directory esistente

Un'app web non può modificare un file su disco senza l'autorizzazione esplicita dell'utente.

Richiesta di autorizzazione

Se una persona vuole salvare le modifiche a un file a cui ha precedentemente concesso l'accesso in lettura, il browser visualizza una richiesta di autorizzazione per consentire al sito di scrivere le modifiche sul disco. La richiesta di autorizzazione può essere attivata solo da un gesto dell'utente, ad esempio facendo clic su un pulsante Salva.

Richiesta di autorizzazione mostrata prima di salvare un file.
Prompt mostrato agli utenti prima che al browser venga concessa l'autorizzazione di scrittura su un file esistente.

In alternativa, un'app web che modifica più file, ad esempio un IDE, può anche chiedere l'autorizzazione per salvare le modifiche al momento dell'apertura.

Se l'utente sceglie Annulla e non concede l'accesso in scrittura, l'app web non può salvare le modifiche al file locale. Deve fornire all'utente un metodo alternativo per salvare i dati, ad esempio fornendo un modo per "scaricare" il file o salvare i dati nel cloud.

Trasparenza

Icona Omnibox
Icona della barra degli indirizzi che indica che l'utente ha concesso al sito web l'autorizzazione a salvare in un file locale.

Una volta che un utente ha concesso l'autorizzazione a un'app web per salvare un file locale, il browser mostra un'icona nella barra degli indirizzi. Se fai clic sull'icona, si apre un popup che mostra l'elenco dei file a cui l'utente ha dato accesso. L'utente può sempre revocare l'accesso, se lo desidera.

Persistenza delle autorizzazioni

L'app web può continuare a salvare le modifiche al file senza chiedere conferma finché non sono chiuse tutte le schede per la relativa origine. Una volta chiusa una scheda, il sito perde tutto l'accesso. La volta successiva che l'utente utilizzerà l'app web, gli verrà chiesto di nuovo di accedere ai file.

Feedback

Vorremmo conoscere la tua esperienza con l'API File System Access.

Fornisci informazioni sul design dell'API

C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o proprietà per implementare la tua idea? Hai domande o commenti sul modello di sicurezza?

Problemi con l'implementazione?

Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalla specifica?

  • Segnala un bug all'indirizzo https://new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile, le istruzioni per la riproduzione e imposta Componenti su Blink>Storage>FileSystem. Glitch è ideale per condividere riproduzioni rapide.

Hai intenzione di utilizzare l'API?

Vuoi utilizzare l'API File System Access nel tuo sito? Il tuo supporto pubblico ci aiuta a dare la priorità alle funzionalità e mostra ad altri fornitori di browser quanto sia fondamentale supportarle.

Link utili

Ringraziamenti

La specifica dell'API File System Access è stata scritta da Marijn Kruisselbrink.