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 in file e cartelle sul dispositivo dell'utente.

Che cos'è l'API File System Access?

L'API File System Access consente agli sviluppatori di creare potenti app web che interagiscono con sul dispositivo locale dell'utente, ad esempio gli IDE, gli editor di foto e video, gli editor di testo e altro ancora. Dopo il giorno un utente concede l'accesso a un'app web, questa API gli consente di leggere o salvare le modifiche direttamente nei file e cartelle sul dispositivo dell'utente. Oltre a leggere e scrivere file, l'API File System Access fornisce di aprire una directory e 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 sarà che conoscete meglio. Ti consiglio di leggerlo comunque, perché non tutti i sistemi sono uguali.

L'API File System Access è supportata nella maggior parte dei browser Chromium su Windows, macOS, ChromeOS e Linux. Un'eccezione degna di nota è Brave, dove si trova 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 File System Access, ho scritto un singolo file di testo Editor. Consente di aprire un file di testo, modificarlo, salvare le modifiche su disco o avviare creare un nuovo file e salvare le modifiche su disco. Non è niente di particolare, ma fornisce abbastanza 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 File System Access è supportata, verifica se il metodo di selettore che ti interessa esista.

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.

Lettura di 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 accesso all'API File System Access window.showOpenFilePicker() Viene visualizzata una finestra di dialogo del selettore file, e chiede all'utente di selezionare un file. Dopo aver selezionato un file, l'API restituisce un array di file handle. Un parametro options facoltativo ti consente di influenzare il comportamento del selettore file, ad esempio 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. Questo è perfetto per un editor di testo.

Come molte altre potenti API, la chiamata a showOpenFilePicker() deve essere eseguita in contesto e deve essere chiamato 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 ha selezionato un file, showOpenFilePicker() restituisce un array di handle, in questo caso un array a un elemento con un FileSystemFileHandle che contiene le proprietà e 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à necessarie per salvare le modifiche apportate al file o per eseguire altre operazioni sui file.

Leggere un file dal file system

Ora che hai un handle per un file, puoi ottenere le proprietà del file o accedere al file stesso. Per il momento, ne leggerò il contenuto. La chiamata a handle.getFile() restituisce un valore File contenente un blob. Per ottenere i dati dal blob, chiama uno dei suo metodi, (slice(), stream(), text() oppure 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 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 in modo da leggere l'oggetto modificato e i dati di Google Cloud.

Riassumendo

Quando gli utenti fanno clic sul pulsante Apri, il browser mostra un selettore file. Una volta selezionato un file, l'app 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;
});

Scrivi il file nel file system locale

Nell'editor di testo, sono disponibili due modi per salvare un file: Salva e Salva con nome. Salva scrive le modifiche al file originale utilizzando l'handle di file recuperato in precedenza. Ma salva As: crea un nuovo file e richiede un nuovo handle.

Crea un nuovo file

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

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

Salva le modifiche su disco

Puoi trovare tutto il codice per salvare le modifiche in un file nella mia demo dell'editor di testo su GitHub. Le interazioni principali con il file system fs-helpers.js Nella sua forma più semplice, il processo è simile al seguente codice. Esaminerò 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 dei dati su disco utilizza un oggetto FileSystemWritableFileStream, una sottoclasse di WritableStream. Crea lo stream chiamando createWritable() sul file e gestire l'oggetto. Quando viene chiamato createWritable(), il browser verifica innanzitutto se l'utente ha concesso l'accesso di scrittura sul file. Se non è stata concessa l'autorizzazione in scrittura, il browser richiede per richiedere l'autorizzazione all'utente. Se l'autorizzazione non viene concessa, createWritable() genera un DOMException e l'app non sarà in grado di scrivere sul file. Nell'editor di testo, il parametro DOMException oggetti vengono gestiti nel metodo saveFile().

Il metodo write() accetta una stringa, che è necessaria per un editor di testo. Ma può anche richiedere BufferSource o Blob. Ad esempio, puoi indirizzare uno stream direttamente Questo:

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

All'interno dello stream, puoi anche seek() oppure truncate() per aggiornare in una posizione specifica o ridimensionarlo.

Specifica di un nome file e di una directory iniziale suggeriti

In molti casi potresti volere che l'app suggerisca un nome file o una posizione predefiniti. Ad esempio, un messaggio potrebbe voler suggerire un nome file predefinito Untitled Text.txt anziché Untitled. Tu puoi raggiungere questo obiettivo trasmettendo 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 directory iniziale predefinita. Se stai creando un editor di testo, ti consigliamo di avvia la finestra di dialogo per il salvataggio o l'apertura del file nella cartella predefinita documents, mentre per un'immagine editor, potresti iniziare dalla cartella pictures predefinita. Puoi suggerire un inizio predefinito directory passando una proprietà startIn a showSaveFilePicker, showDirectoryPicker() showOpenFilePicker metodi come questo.

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

L'elenco di directory di sistema note è:

  • desktop: la directory desktop dell'utente, se questo elemento esiste.
  • documents: directory in cui vengono generalmente archiviati i documenti creati dall'utente.
  • downloads: directory in cui generalmente vengono 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 i video o i film.

Oltre alle directory di sistema note, puoi passare anche un handle esistente di un file o di una directory come un 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 file

A volte le applicazioni hanno selettori diversi per scopi diversi. Ad esempio, un file RTF può consentire all'utente di aprire i file di testo, ma anche di importare immagini. Per impostazione predefinita, ogni file si aprirebbe nell'ultima posizione che ricordi. Puoi aggirare questo problema archiviando valori id per ogni tipo di selettore. Se viene specificato un valore id, l'implementazione del selettore file ricorda un separata per ultima directory utilizzata per id.

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

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

Archiviazione di handle di file o di directory in IndexedDB

Gli handle di file e di directory sono serializzabili, il che significa che puoi salvare un file handle di directory a IndexedDB oppure chiama postMessage() per inviarli tra lo stesso livello di primo livello origine dati.

Il salvataggio di file o handle di directory in IndexedDB significa che puoi archiviare lo stato o ricordare quale i file o le directory a cui stava lavorando un utente. In questo modo è possibile mantenere un elenco di o modificati, propone di riaprire l'ultimo file all'apertura dell'app, ripristinare il funzionamento precedente directory e altro ancora. Nell'editor di testo, archivio un elenco dei cinque file più recenti di cui l'utente ha aperta, in modo da poter accedere di nuovo a quei file.

L'esempio di codice riportato di seguito mostra l'archiviazione e il recupero di un handle di file e un handle di directory. Puoi vedi la funzionalità 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 non sono sempre persistenti tra una sessione e l'altra, è necessario verificare se l'utente ha concesso l'autorizzazione al file o alla directory utilizzando queryPermission(). In caso contrario, chiama requestPermission() per richiederlo (nuovamente). Questa operazione funziona allo stesso modo per gli handle di file e directory. Tu devi eseguire fileOrDirectoryHandle.requestPermission(descriptor) o rispettivamente fileOrDirectoryHandle.queryPermission(descriptor).

Nell'editor di testo, ho creato un metodo verifyPermission() che controlla se l'utente ha già autorizzata 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 prompt di autorizzazione. l'utente vede un prompt all'apertura del file e concede l'autorizzazione sia in lettura che in scrittura.

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 visualizzata una FileSystemDirectoryHandle che ti consente di enumerare e accedere ai file della directory. Per impostazione predefinita, leggi ai file nella directory, ma se hai bisogno dell'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 accedere a ciascun file utilizzando getFile(), ad esempio, per ottenere il singolo le dimensioni dei file, non utilizzare await per ogni risultato in sequenza, ma elabora tutti i file in parallelo, ad esempio usando 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 getFileHandle() o rispettivamente getDirectoryHandle() . Passando un oggetto options facoltativo con una chiave create e un valore booleano true o false, puoi stabilire se è necessario creare un nuovo file o una nuova cartella se non esiste.

// 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(), con il nome appropriato. Per risolvere il problema, può essere un elemento figlio 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 contenuti con removeEntry(). Per le cartelle, l'eliminazione può essere facoltativamente ricorsiva e può includere da tutte le sottocartelle e dai file in esse contenuti.

// 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 di directory, chiama remove() su un FileSystemFileHandle o FileSystemDirectoryHandle per rimuoverla.

// 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() sul FileSystemHandle. FileSystemHandle ha le interfacce secondarie FileSystemFileHandle e FileSystemDirectoryHandle. Il metodo move() richiede uno o due parametri. Il primo può una stringa con il nuovo nome o FileSystemDirectoryHandle alla cartella di destinazione. Nella nel secondo caso, il secondo parametro facoltativo è una stringa con il nuovo nome, quindi lo spostamento e la ridenominazione avvengono 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

La Interfacce di trascinamento dell'HTML abilita le applicazioni web ad accettare file trascinati e rilasciati su una pagina web. Durante un'operazione di trascinamento, i file e gli elementi della directory trascinati vengono associati rispettivamente con voci di file e voci di directory. DataTransferItem.getAsFileSystemHandle() restituisce una promessa con un oggetto FileSystemFileHandle se l'elemento trascinato è un file e promette un oggetto FileSystemDirectoryHandle se l'elemento trascinato è una directory. Il seguente elenco la mostra in azione. Tieni presente che l'interfaccia di trascinamento DataTransferItem.kind è "file" per i file e 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 origine della pagina. Sebbene i browser in genere lo implementino, memorizzando i contenuti di questo il file system privato di origine su disco da qualche parte, non è previsto che i contenuti siano accessibili. Analogamente, non ci si aspetta che i file o le directory con nomi corrispondenti esistono nomi secondari del file system privato di origine. Anche se il browser può far sembrare che esistono dei file, internamente (poiché 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 one-to-one da qualche parte sul disco rigido. Puoi operare normalmente su il file system privato di origine dopo aver ottenuto l'accesso alla radice 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

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

Origine

Accesso a 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 all'interfaccia contenuti. In Chromium 102 e versioni successive, esiste un altro metodo sul file system privato di origine per semplificare l'accesso ai file: createSyncAccessHandle() (per operazioni sincrone di lettura e scrittura). È esposta il giorno FileSystemFileHandle, ma esclusivamente 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 });

Polyfill

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">, ma questo attiva un download programmatico e non consente la sovrascrittura dei file esistenti.
  • Il metodo showDirectoryPicker() può essere in qualche modo emulato con il metodo Elemento <input type="file" webkitdirectory>.

Abbiamo sviluppato una libreria chiamata browser-fs-access che utilizza l'interfaccia l'API System Access, ove possibile, e che si basa su queste migliori opzioni in tutte le altre d'uso diversi.

Sicurezza e autorizzazioni

Il team di Chrome ha progettato e implementato l'API File System Access utilizzando i principi fondamentali definita in Controllo dell'accesso a funzionalità avanzate della piattaforma web, tra cui le controllo e trasparenza, ed ergonomia dell'utente.

Apertura o salvataggio di un file nuovo

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

Quando apre un file, l'utente fornisce l'autorizzazione a leggere un file o una directory utilizzando il selettore file. Il selettore di file di apertura può essere mostrato con un gesto dell'utente solo quando viene eseguito da un contesto. Se gli utenti cambiano idea, possono annullare la selezione nel file e il sito non ha accesso a nulla. Questo è lo stesso comportamento del Elemento <input type="file">.

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

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

Cartelle limitate

Per contribuire a proteggere gli utenti e i loro dati, il browser potrebbe limitare la possibilità degli utenti di salvare dati in determinati ad esempio le cartelle principali del sistema operativo come Windows, le cartelle della Libreria macOS. In questo caso, il browser mostra un messaggio e chiede all'utente di scegliere un altro .

Modifica di un file o di una directory esistente

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

Richiesta di autorizzazione

Se una persona desidera salvare le modifiche a un file a cui ha precedentemente 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 Salva .

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

In alternativa, un'app web che modifica più file, ad esempio un IDE, può chiedere l'autorizzazione per salvare 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 nel locale. Deve fornire all'utente un metodo alternativo per salvare i propri dati, ad esempio esempio offrendo un modo per "scaricare" il file o salvare i dati sul cloud.

Trasparenza

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

Dopo che un utente ha concesso a un'app web l'autorizzazione a salvare un file locale, nel browser viene visualizzata un'icona nella barra degli indirizzi. Se fai clic sull'icona, si apre un pop-over che mostra l'elenco dei file forniti dall'utente a cui accedono. L'utente può sempre revocare l'accesso, se lo desidera.

Persistenza dell'autorizzazione

L'app web può continuare a salvare le modifiche apportate al file senza chiedere conferma fino a quando non tutte le schede le origini dati sono chiuse. Una volta chiusa una scheda, il sito perde ogni accesso. La volta successiva che l'utente utilizza nell'app web, gli verrà chiesto di nuovo l'accesso ai file.

Feedback

Vorremmo 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 le proprietà necessarie per implementare la tua idea? Hai una domanda o un commento sulla sicurezza modello?

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. Includi il maggior numero di dettagli possibile, istruzioni per la riproduzione e imposta Componenti su Blink>Storage>FileSystem. Glitch è perfetto per la condivisione rapida di riproduzioni.

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à funzionalità di sicurezza e mostra ad altri fornitori di browser quanto sia fondamentale supportarli.

Link utili

Ringraziamenti

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