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

L'API File System Access consente alle app web di leggere o salvare le modifiche direttamente su file e cartelle sul dispositivo dell'utente.

Che cos'è l'API File System Access?

L'API File System Access (precedentemente nota come API Native File System e prima era chiamata API Writeable Files) consente agli sviluppatori di creare potenti app web che interagiscono con i file sul dispositivo locale dell'utente, come 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 consente di leggere o salvare le modifiche direttamente sui file e sulle cartelle sul dispositivo dell'utente. Oltre a leggere e scrivere file, l'API File System Access offre la possibilità di aprire una directory ed enumerarne i contenuti.

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

L'API File System Access è attualmente supportata nella maggior parte dei browser Chromium su Windows, macOS, ChromeOS e Linux. Un'eccezione è Brave, dove al momento è disponibile solo dietro contrassegno. Android supporta la parte del file system privato di origine dell'API a partire da Chromium 109. Al momento non sono disponibili metodi di selezione, ma puoi monitorare i potenziali progressi aggiungendo crbug.com/1011535.

Utilizzo dell'API File System Access

Per dimostrare la potenza e l'utilità dell'API File System Access, ho scritto un singolo editor di testo per i file. Ti consente di aprire un file di testo, modificarlo, salvare le modifiche su disco o avviare un nuovo file e salvare le modifiche su disco. Non è niente di speciale, ma offre abbastanza per aiutarti a capire i concetti.

Supporto del browser

Supporto dei browser

  • 86
  • 86
  • x
  • x

Fonte

Prova

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

Lettura di un file dal file system locale

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

Chiedi all'utente di scegliere un file da leggere

Il punto di ingresso all'API File System Access è window.showOpenFilePicker(). Quando viene chiamato, mostra una finestra di dialogo selettore file e chiede all'utente di selezionare un file. Dopo che hanno selezionato un file, l'API restituisce un array di handle di file. Un parametro options facoltativo consente di influenzare il comportamento del selettore file, ad esempio consentendo all'utente di selezionare più file, directory o tipi di file diversi. Senza alcuna opzione specificata, il selettore file consente all'utente di selezionare un singolo file. È perfetto per un editor di testo.

Come molte altre API potenti, la chiamata a showOpenFilePicker() deve avvenire in un contesto sicuro e dall'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 seleziona un file, showOpenFilePicker() restituisce un array di handle, in questo caso un array di un elemento con un 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 seguito. Sarà necessario salvare le modifiche apportate al file o eseguire qualsiasi altra operazione sul file.

Leggere un file dal file system

Ora che hai un handle, puoi recuperarne le proprietà o accedere al file stesso. Per ora, ne leggerò semplicemente il contenuto. La chiamata a handle.getFile() restituisce un oggetto File, che contiene un blob. Per recuperare i dati dal blob, chiama uno dei suo 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 a condizione che il file sottostante non sia stato modificato. Se il file sul disco viene modificato, l'oggetto File diventa illeggibile e dovrai chiamare di nuovo getFile() per ottenere un nuovo oggetto File e leggere i dati modificati.

Riassumendo

Quando gli utenti fanno clic sul pulsante Apri, il browser mostra un selettore di file. Dopo che l'utente ha selezionato un file, l'app leggi 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;
});

Scrivi il file nel file system locale

Esistono due modi per salvare un file nell'editor di testo: Salva e Salva con nome. Salva riporta semplicemente le modifiche nel file originale utilizzando l'handle del file recuperato in precedenza. Tuttavia, l'opzione Salva con nome crea un nuovo file e pertanto richiede un nuovo handle.

Crea un nuovo file

Per salvare un file, chiama showSaveFilePicker(), che mostra il selettore file in modalità "Salva" e consente 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 modifiche su disco

Puoi trovare tutto il codice per salvare le modifiche a un file nella mia demo dell'editor di testo su GitHub. Le interazioni con il file system di base sono in fs-helpers.js. In parole povere, il processo è simile al codice seguente. Analizzerò ogni passaggio e lo spiegherò.

// 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 di dati su disco utilizza un oggetto FileSystemWritableFileStream, una sottoclasse di WritableStream. Crea il flusso chiamando createWritable() sull'oggetto handle 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 richiede all'utente l'autorizzazione. Se l'autorizzazione non viene concessa, createWritable() genera 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() utilizza una stringa, necessaria a un editor di testo. Tuttavia, può utilizzare anche una BufferSource, o un Blob. Ad esempio, puoi reindirizzare direttamente un flusso:

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 seek() o truncate() all'interno dello stream per aggiornare il file in una posizione specifica o ridimensionarlo.

Specificare un nome file suggerito e la directory di avvio

In molti casi potresti volere che l'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 ottenere questo risultato passando una proprietà suggestedName come parte delle opzioni di showSaveFilePicker.

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

Lo stesso vale per la directory di avvio predefinita. Se stai creando un editor di testo, potresti voler avviare il salvataggio del file o la finestra di dialogo di apertura dei file nella cartella documents predefinita, mentre nel caso di un editor di immagini è preferibile avviare la cartella pictures predefinita. Puoi suggerire una directory start predefinita passando una proprietà startIn ai metodi showSaveFilePicker, showDirectoryPicker() o showOpenFilePicker.

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

L'elenco delle directory di sistema note è il seguente:

  • desktop: la directory desktop dell'utente, se esiste.
  • documents: directory in cui vengono generalmente archiviati i documenti creati dall'utente.
  • downloads: directory in cui vengono generalmente archiviati i file scaricati.
  • music: directory in cui vengono generalmente archiviati i file audio.
  • pictures: directory in cui vengono generalmente archiviate foto e altre immagini statiche.
  • videos: directory in cui vengono generalmente archiviati video/film.

Oltre alle directory di sistema 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 dei diversi selettori di file

A volte le applicazioni hanno selettori diversi per scopi diversi. Ad esempio, un editor RTF potrebbe consentire all'utente di aprire file di testo, ma anche di importare immagini. Per impostazione predefinita, ogni selettore file si apre nell'ultima posizione memorizzata. Puoi aggirare questa limitazione memorizzando i valori id per ogni tipo di selettore. Se viene specificato un id, l'implementazione del selettore file memorizza una directory dell'ultima utilizzata separata per quel id.

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

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

Archiviazione degli handle dei file o delle directory in IndexedDB

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

Se salvi gli handle dei file o della directory in IndexedDB, puoi archiviare lo stato o ricordare i file o le directory su cui stava lavorando un utente. In questo modo è possibile mantenere un elenco dei file aperti o modificati di recente, offrire di riaprire l'ultimo file all'apertura dell'app, ripristinare la directory di lavoro precedente e altro ancora. Nell'editor di testo, conservi un elenco dei cinque file più recenti aperti dall'utente, in modo da poter accedere di nuovo facilmente ai file.

L'esempio di codice riportato di seguito mostra l'archiviazione e il recupero di un handle di file e di un handle di directory. Puoi vedere come funziona su Glitch. (Uso la libreria idb-keyval per brevità).

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 al momento non sono persistenti tra le sessioni, devi verificare se l'utente ha concesso l'autorizzazione al file o alla directory utilizzando queryPermission(). Se non l'ha fatto, chiama requestPermission() per richiederlo di nuovo. Funziona allo stesso modo per gli handle di file e directory. Devi eseguire rispettivamente fileOrDirectoryHandle.requestPermission(descriptor) o fileOrDirectoryHandle.queryPermission(descriptor).

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 all'apertura del file e concede l'autorizzazione di lettura e scrittura al file.

Apertura di una directory ed enumerazione dei contenuti

Per enumerare tutti i file di una directory, chiama showDirectoryPicker(). L'utente seleziona una directory in un selettore, dopodiché viene restituito un FileSystemDirectoryHandle, che ti 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.

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

Se devi inoltre accedere a ogni file tramite getFile(), ad esempio per ottenere le singole dimensioni, non utilizzare await per ogni risultato in sequenza, ma elabora tutti i file in parallelo, ad esempio tramite Promise.all().

const butDir = document.getElementById('butDirectory');
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 getFileHandle() o rispettivamente il metodo getDirectoryHandle(). Passando un oggetto options facoltativo con una chiave di create e un valore booleano di true o false, puoi determinare se è necessario creare un nuovo file o una nuova cartella, qualora non esistano.

// 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. Per farlo, puoi usare il metodo resolve() denominato 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"]

Eliminazione di file e cartelle in una directory

Se hai ottenuto l'accesso a una directory, puoi eliminare i file e le cartelle al suo interno con il metodo removeEntry(). Per le cartelle, l'eliminazione può facoltativamente essere 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 });

Eliminare direttamente un file o una cartella

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

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

Ridenominazione e spostamento di file e cartelle

I file e le cartelle possono essere rinominati o spostati in una nuova posizione chiamando move() nell'interfaccia di 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 della cartella di destinazione. Nel secondo caso, il secondo parametro facoltativo è una stringa con il nuovo nome, quindi lo spostamento e la ridenominazione possono avvenire 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 trascinamento

Le interfacce di trascinamento HTML consentono alle applicazioni web di accettare file trascinati e rilasciati su una pagina web. Durante un'operazione di trascinamento, gli elementi del file e della directory trascinati vengono associati rispettivamente alle voci dei file e delle 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. L'elenco di seguito mostra questo comportamento. Tieni presente che DataTransferItem.kind dell'interfaccia di trascinamento è "file" per file e 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 suggerito dal nome, è privato per l'origine della pagina. Sebbene i browser in genere implementino questa funzionalità ripristinando i contenuti di questo file system privato dell'origine su disco, non è previsto che i contenuti siano facilmente accessibili dall'utente. Allo stesso modo, non è previsto che esistano file o directory con nomi corrispondenti ai nomi degli elementi secondari del file system privato di origine. Sebbene il browser possa far sembrare che esistano file, internamente (dal momento che si tratta di un file system privato di origine), il browser potrebbe archiviare questi "file" in un database o in qualsiasi altra struttura di dati. Essenzialmente, se usi questa API, non aspettarti di trovare i file creati corrispondenti uno a uno da qualche parte sul disco rigido. Puoi operare come di consueto sul file system privato di origine dopo aver accesso al file system principale FileSystemDirectoryHandle.

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

  • 86
  • 86
  • 111
  • 15.2

Fonte

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

Il file system privato di origine fornisce accesso facoltativo a un tipo speciale di file altamente ottimizzato per le prestazioni, ad esempio offrendo accesso in scrittura ed esclusivo ai contenuti di un file. In Chromium 102 e versioni successive, esiste un altro metodo sul file system privato di origine per semplificare l'accesso ai file: createSyncAccessHandle() (per le operazioni di lettura e scrittura sincrone). È esposto il giorno FileSystemFileHandle, ma esclusivamente nei 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 });

Poliriempimento

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 la sovrascrittura dei 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 che utilizza le migliori opzioni disponibili 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 nella sezione Controllare l'accesso alle funzionalità avanzate della piattaforma web, tra cui controllo e trasparenza dell'utente e ergonomia degli utenti.

Apertura o salvataggio di un nuovo file

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

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

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

Analogamente, quando un'app web vuole salvare un nuovo file, il browser mostra il selettore di file di salvataggio, che consente all'utente di specificare il nome e la posizione del nuovo file. Poiché vengono salvati un nuovo file sul dispositivo (anziché sovrascrivere uno esistente), il selettore file concede all'app l'autorizzazione di scrittura nel file.

Cartelle con restrizioni

Per proteggere gli utenti e i loro dati, il browser potrebbe limitare la capacità dell'utente di salvare in determinate cartelle, ad esempio le cartelle principali del sistema operativo come Windows, le cartelle della libreria di macOS e così via. In questo caso, il browser mostra un messaggio e chiede all'utente di scegliere una cartella diversa.

Modifica di un file o di una directory esistente

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

Richiesta di autorizzazione

Se una persona vuole salvare le modifiche apportate a un file a cui in precedenza aveva concesso l'accesso in lettura, il browser mostra una richiesta di autorizzazione, che richiede al sito l'autorizzazione a scrivere 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 visualizzata prima del salvataggio di un file.
Richiesta mostrata 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. Dovrebbe fornire all'utente un metodo alternativo per salvare i propri dati, ad esempio fornendo un modo per "scaricare" il file, salvando i dati nel cloud e così via.

Trasparenza

Icona omnibox
Icona omnibox che indica che l'utente ha concesso al sito web l'autorizzazione a salvare in un file locale.

Dopo che un utente ha concesso a un'app web l'autorizzazione a salvare un file locale, il browser mostra un'icona nella barra degli URL. Se fai clic sull'icona, viene aperto un popup che mostra l'elenco dei file a cui l'utente ha concesso l'accesso. L'utente può revocare facilmente l'accesso, se lo desidera.

Persistenza delle autorizzazioni

L'app web può continuare a salvare le modifiche al file senza chiedere conferma finché non vengono chiuse tutte le schede relative alla relativa origine. Una volta chiusa una scheda, il sito perde completamente l'accesso. La volta successiva che l'utente utilizza l'app web, gli verrà richiesto nuovamente di accedere ai file.

Feedback

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

Parlaci della progettazione dell'API

C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o proprietà di cui hai bisogno 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 dalle specifiche?

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

Prevedi di utilizzare l'API?

Pensi di utilizzare l'API File System Access sul tuo sito? Il supporto pubblico ci aiuta a dare la priorità alle funzionalità e mostra ad altri fornitori di browser l'importanza di supportarle.

Link utili

Ringraziamenti

Le specifiche dell'API File System Access sono state scritte da Marijn Kruisselbrink.