L'API File System Access permet aux applications Web de lire ou d'enregistrer les modifications directement dans les fichiers et les dossiers de l'appareil de l'utilisateur.
Qu'est-ce que l'API File System Access ?
L'API File System Access permet aux développeurs de créer des applications Web performantes qui interagissent avec les fichiers sur l'appareil local de l'utilisateur, tels que les IDE, les éditeurs de photos et de vidéos, les éditeurs de texte, etc. Après lorsqu'un utilisateur autorise l'accès à une application Web, cette API lui permet de lire ou d'enregistrer les modifications directement dans les fichiers et dossiers sur l'appareil de l'utilisateur. Outre la lecture et l'écriture de fichiers, l'API File System Access fournit la possibilité d'ouvrir un répertoire et d'énumérer son contenu.
Si vous avez déjà travaillé avec la lecture et l'écriture de fichiers, ce que je vais partager sera principalement que vous connaissez déjà. Je vous encourage quand même à le lire, car tous les systèmes ne se ressemblent pas.
L'API File System Access est compatible avec la plupart des navigateurs Chromium sur Windows, macOS, ChromeOS et Linux. Une exception notable est Brave : actuellement disponibles avec un drapeau. La compatibilité avec Android est en cours d'examen par le biais de crbug.com/1011535.
Utiliser l'API File System Access
Pour démontrer la puissance et l'utilité de l'API File System Access, j'ai écrit un seul fichier texte éditeur. Il vous permet d'ouvrir un fichier texte, de le modifier, d'enregistrer les modifications sur le disque ou de commencer un nouveau fichier et enregistrer les modifications sur le disque. Il n'a rien d'extraordinaire, mais il offre suffisamment d'options pour vous aider pour comprendre les concepts.
Prise en charge des navigateurs
Navigateurs pris en charge
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
Détection de caractéristiques
Pour savoir si l'API File System Access est compatible, vérifiez si la méthode de sélection qui vous intéresse existe.
if ('showOpenFilePicker' in self) {
// The `showOpenFilePicker()` method of the File System Access API is supported.
}
Essayer
Découvrez l'API File System Access en action dans le text Editor (éditeur de texte) de votre site Web.
Lire un fichier à partir du système de fichiers local
Le premier cas d'utilisation que je veux aborder est de demander à l'utilisateur de choisir un fichier, puis de l'ouvrir et de le lire à partir du disque.
Demander à l'utilisateur de choisir un fichier à lire
Le point d'entrée de l'API File System Access est
window.showOpenFilePicker()
Lorsqu'elle est appelée, elle affiche
une boîte de dialogue de sélection de fichier,
et invite l'utilisateur à sélectionner un fichier. Une fois le fichier sélectionné, l'API renvoie un tableau de fichiers
poignées. Un paramètre options
facultatif vous permet d'influencer le comportement de l'outil de sélection de fichier, par exemple
par exemple, en permettant à l'utilisateur de sélectionner plusieurs fichiers,
répertoires ou différents types de fichiers.
Si aucune option n'est spécifiée, le sélecteur de fichier permet à l'utilisateur de sélectionner un seul fichier. C'est
parfait pour
un éditeur de texte.
Comme de nombreuses autres API performantes, l'appel de showOpenFilePicker()
doit s'effectuer de manière sécurisée
le contexte, et doivent être appelées à partir d'un geste de l'utilisateur.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});
Une fois que l'utilisateur a sélectionné un fichier, showOpenFilePicker()
renvoie un tableau de handle, dans ce cas,
un tableau à un élément avec un FileSystemFileHandle
contenant les propriétés et
nécessaires pour interagir avec le fichier.
Il est utile de garder une référence au gestionnaire de fichier afin de pouvoir l'utiliser ultérieurement. Ce sera nécessaire pour enregistrer les modifications apportées au fichier ou pour effectuer toute autre opération sur le fichier.
Lire un fichier à partir du système de fichiers
Maintenant que vous disposez d'un handle vers un fichier, vous pouvez obtenir ses propriétés ou accéder au fichier lui-même.
Pour l’instant, je vais
lire son contenu. L'appel de handle.getFile()
renvoie un File
, qui contient un blob. Pour récupérer les données de l'objet blob, appelez l'une de ses
méthodes, (slice()
,
stream()
,
text()
ou
arrayBuffer()
).
const file = await fileHandle.getFile();
const contents = await file.text();
L'objet File
renvoyé par FileSystemFileHandle.getFile()
n'est lisible que si le
le fichier sous-jacent
sur le disque n’a pas changé. Si le fichier sur le disque est modifié, l'objet File
devient
illisible et vous devrez appeler à nouveau getFile()
pour obtenir un nouvel objet File
permettant de lire les modifications
données.
Synthèse
Lorsque les utilisateurs cliquent sur le bouton Ouvrir, le navigateur affiche un sélecteur de fichier. Une fois qu'ils ont sélectionné un fichier,
l'application lit le contenu et le place dans 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;
});
Écrire le fichier dans le système de fichiers local
Dans l'éditeur de texte, vous pouvez enregistrer un fichier de deux façons: Enregistrer et Enregistrer sous. Enregistrer écrit les modifications dans le fichier d'origine à l'aide du traitement de fichier récupéré précédemment. Mais Enregistrer As crée un fichier, ce qui nécessite un nouveau handle de fichier.
Créer un fichier
Pour enregistrer un fichier, appelez showSaveFilePicker()
, qui affiche l'outil de sélection de fichier.
dans "enregistrer" permettant à l'utilisateur de choisir le nouveau fichier qu'il souhaite utiliser pour l'enregistrement. Pour le texte
éditeur, je voulais également qu'il ajoute automatiquement une extension .txt
. J'ai donc fourni quelques
paramètres.
async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}
Enregistrer les modifications sur le disque
Vous trouverez tout le code permettant d'enregistrer les modifications apportées à un fichier dans la démo de mon éditeur de texte sur
GitHub Les principales interactions
du système de fichiers sont
fs-helpers.js
Dans sa forme la plus simple, le processus se présente comme suit :
Je vais passer en revue chaque étape et l'expliquer.
// 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();
}
L'écriture de données sur le disque utilise un objet FileSystemWritableFileStream
, une sous-classe
sur WritableStream
. Créez le flux en appelant createWritable()
sur le fichier
handle. Lorsque createWritable()
est appelé, le navigateur vérifie d'abord si l'utilisateur a accordé
l'autorisation d'écriture sur le fichier. Si l'autorisation d'écriture n'a pas été accordée, le navigateur vous demande
à l'utilisateur pour obtenir l'autorisation. Si l'autorisation n'est pas accordée, createWritable()
génère une
DOMException
, et l'application ne pourra pas écrire dans le fichier. Dans l'éditeur de texte,
Les objets DOMException
sont gérés dans la méthode saveFile()
.
La méthode write()
accepte une chaîne, qui est nécessaire à un éditeur de texte. Mais cela peut aussi prendre
un BufferSource ou un Blob. Par exemple, vous pouvez diriger un flux directement vers
comme suit:
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.
}
Vous pouvez également seek()
ou truncate()
dans le flux pour mettre à jour le
à une position spécifique, ou redimensionner le fichier.
Spécification d'un nom de fichier suggéré et d'un répertoire de départ
Dans de nombreux cas, vous souhaiterez peut-être que votre application suggère un nom de fichier ou un emplacement par défaut. Par exemple, un texte
l'éditeur peut suggérer le nom de fichier par défaut Untitled Text.txt
plutôt que Untitled
. Toi
Pour ce faire, transmettez une propriété suggestedName
dans les options showSaveFilePicker
.
const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});
Il en va de même pour le
répertoire de départ par défaut. Si vous créez un éditeur de texte, vous voudrez peut-être
lancer la boîte de dialogue d'enregistrement ou d'ouverture de fichier dans le dossier documents
par défaut, tandis que pour une image,
éditeur, vous devriez peut-être commencer dans le dossier par défaut pictures
. Vous pouvez suggérer un début par défaut
en transmettant une propriété startIn
à showSaveFilePicker
, showDirectoryPicker()
ou
showOpenFilePicker
comme ceci.
const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});
Voici la liste des répertoires système connus:
desktop
: répertoire du bureau de l'utilisateur, le cas échéantdocuments
: répertoire dans lequel les documents créés par l'utilisateur sont généralement stockés.downloads
: répertoire dans lequel les fichiers téléchargés sont généralement stockés.music
: répertoire dans lequel les fichiers audio sont généralement stockés.pictures
: répertoire dans lequel les photos et autres images fixes sont généralement stockées.videos
: répertoire dans lequel les vidéos ou les films sont généralement stockés
Outre les répertoires système bien connus, vous pouvez également transmettre un identifiant de fichier ou de répertoire existant en tant que
une valeur pour startIn
. La boîte de dialogue s'ouvrira alors dans le même répertoire.
// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});
Spécifier l'objectif des différents sélecteurs de fichiers
Parfois, les applications disposent de différents sélecteurs pour des objectifs différents. Par exemple, un texte enrichi
peut permettre à l'utilisateur d'ouvrir des fichiers texte, mais également d'importer des images. Par défaut, chaque fichier
l'outil de sélection s'ouvrira au dernier emplacement mémorisé. Vous pouvez contourner ce problème en stockant des valeurs id
pour chaque type de sélecteur. Si un id
est spécifié, l'implémentation du sélecteur de fichier mémorise un
d'un répertoire distinct utilisé en dernier pour ce id
.
const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});
const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});
Stocker des descripteurs de fichier ou de répertoire dans IndexedDB
Les gestionnaires de fichiers et de répertoires sont sérialisables, ce qui signifie que vous pouvez enregistrer un fichier ou
gestionnaire de répertoire vers IndexedDB, ou appelez postMessage()
pour les envoyer entre les mêmes instances racine
origine.
L'enregistrement des descripteurs de fichier ou de répertoire dans IndexedDB vous permet de stocker l'état ou de vous souvenir les fichiers ou répertoires sur lesquels un utilisateur travaillait. Cela permet de conserver une liste des éléments récemment ouverts ou modifiés, proposer de rouvrir le dernier fichier à l'ouverture de l'application, restaurer le fichier précédent répertoire, etc. Dans l'éditeur de texte, je stocke la liste des cinq fichiers les plus récents de l'utilisateur ouverts, ce qui permet d’accéder à nouveau à ces fichiers.
L'exemple de code suivant montre comment stocker et récupérer un handle de fichier et un handle de répertoire. Vous pouvez voir ceci sur Glitch. (J'utilise la bibliothèque idb-keyval par souci de concision.)
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);
}
});
Identifiants et autorisations des fichiers ou répertoires stockés
Étant donné que les autorisations ne sont pas toujours conservées d'une session à l'autre, vous devez vérifier si l'utilisateur
a autorisé l'accès au fichier ou au répertoire à l'aide de queryPermission()
. Si ce n'est pas le cas, appelez
requestPermission()
pour la (re)demander. Cela fonctionne de la même manière
pour les gestionnaires de fichiers et de répertoires. Toi
exécuter fileOrDirectoryHandle.requestPermission(descriptor)
ou
fileOrDirectoryHandle.queryPermission(descriptor)
respectivement.
Dans l'éditeur de texte, j'ai créé une méthode verifyPermission()
qui vérifie si l'utilisateur a déjà
l'autorisation accordée et, si nécessaire, fait la demande.
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;
}
En demandant une autorisation d’écriture avec la requête de lecture, j’ai réduit le nombre d’invites d’autorisation ; l'utilisateur voit une invite à l'ouverture du fichier et accorde l'autorisation de le lire et de l'écrire.
Ouvrir un répertoire et énumérer son contenu
Pour énumérer tous les fichiers d'un répertoire, appelez showDirectoryPicker()
. L'utilisateur
sélectionne un répertoire dans un sélecteur, après quoi un FileSystemDirectoryHandle
est
qui vous permet d'énumérer et d'accéder
aux fichiers du répertoire. Par défaut, vous avez lu
aux fichiers du répertoire, mais si vous avez besoin d'un accès en écriture, vous pouvez transmettre
{ mode: 'readwrite' }
à la méthode.
butDir.addEventListener('click', async () => {
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.kind, entry.name);
}
});
Si vous devez également accéder à chaque fichier à l'aide de getFile()
pour, par exemple, obtenir les identifiants
tailles de fichier, n'utilisez pas await
pour chaque résultat de manière séquentielle, mais traitez plutôt tous les fichiers de
parallèle, par exemple, à l'aide de 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));
});
Créer des fichiers et des dossiers dans un répertoire ou y accéder
À partir d'un répertoire, vous pouvez créer des fichiers et des dossiers, ou y accéder à l'aide de l'
getFileHandle()
ou getDirectoryHandle()
respectivement
. En transmettant un objet options
facultatif avec une clé de create
et une valeur booléenne de
true
ou false
, vous pouvez déterminer si un fichier ou un dossier doit être créé s'il n'existe pas.
// 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 });
Résoudre le chemin d'accès à un élément d'un répertoire
Lorsque vous travaillez avec des fichiers ou des dossiers dans un répertoire, il peut être utile de résoudre le chemin d'accès à l'élément
en question. Pour ce faire, utilisez la méthode resolve()
bien nommée. Pour résoudre le problème,
élément peut être un enfant direct ou indirect du répertoire.
// 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"]
Supprimer des fichiers et des dossiers dans un répertoire
Si vous avez obtenu l'accès à un répertoire, vous pouvez supprimer les fichiers et dossiers qu'il contient à l'aide de la commande
removeEntry()
. Pour les dossiers, la suppression peut être récursive et inclure
tous les sous-dossiers et les fichiers qu'ils contiennent.
// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
Supprimer directement un fichier ou un dossier
Si vous avez accès à un handle de fichier ou de répertoire, appelez remove()
sur un FileSystemFileHandle
ou
FileSystemDirectoryHandle
pour la supprimer.
// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();
Renommer et déplacer des fichiers et des dossiers
Les fichiers et les dossiers peuvent être renommés ou déplacés vers un nouvel emplacement en appelant move()
au niveau de la
FileSystemHandle
. FileSystemHandle
comporte les interfaces enfants FileSystemFileHandle
et
FileSystemDirectoryHandle
La méthode move()
accepte un ou deux paramètres. La première peut être
être une chaîne avec le nouveau nom ou un FileSystemDirectoryHandle
vers le dossier de destination. Dans
le second paramètre facultatif est une chaîne portant le nouveau nom. Le déplacement et le changement de nom peuvent donc
s’effectuent en une seule étape.
// 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');
Intégration par glisser-déposer
La
Interfaces HTML de type glisser-déposer
permettre aux applications Web d'accepter
fichiers glissés-déposés
sur une page Web. Lors d'une opération de glisser-déposer, les éléments des fichiers et répertoires déplacés sont associés
avec respectivement des entrées de fichier et des entrées de répertoire. DataTransferItem.getAsFileSystemHandle()
renvoie une promesse avec un objet FileSystemFileHandle
si l'élément déplacé est un fichier et qu'une
promet avec un objet FileSystemDirectoryHandle
si l'élément déplacé est un répertoire. La liste suivante
le montre en action. Notez que l'interface utilisateur de la fonction Glisser-déposer
DataTransferItem.kind
correspond à
"file"
pour les fichiers et les répertoires, tandis que FileSystemHandle.kind
de l'API File System Access est
"file"
pour les fichiers et "directory"
pour les répertoires.
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}`);
}
}
});
Accéder au système de fichiers privé d'origine
Le système de fichiers privé d'origine est un point de terminaison de stockage qui, comme son nom l'indique, est privé
l'origine de la page. Bien que les navigateurs implémentent généralement cette fonctionnalité en persistant
système de fichiers privé d'origine vers le disque quelque part sur le disque, il n'est pas destiné à ce que le contenu soit
accessibles. De même, les fichiers ou répertoires dont le nom correspond à la liste des répertoires
noms des enfants du système de fichiers
privé d’origine existent. Bien que le navigateur puisse
donner l’impression que
de fichiers internes (puisqu'il s'agit d'un système de fichiers d'origine privé), le navigateur peut les stocker
ces "fichiers" dans une base de données ou toute
autre structure de données. En gros, si vous utilisez cette API,
ne vous attendez pas à trouver les fichiers créés qui correspondent à un fichier spécifique quelque part sur le disque dur. Vous pouvez opérer comme d'habitude sur
le système de fichiers privé d'origine une fois que vous avez accès à la racine 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 });
Navigateurs pris en charge
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
-
<ph type="x-smartling-placeholder">
Accéder aux fichiers optimisés pour les performances à partir du système de fichiers privé d'origine
Le système de fichiers d'origine fournit un accès facultatif à un type particulier de fichier
optimisé pour les performances, par exemple en offrant un accès en écriture sur place et exclusif à l'accès
contenus. Dans Chromium 102 et les versions ultérieures, il existe une méthode supplémentaire sur le système de fichiers privé d'origine pour
simplifiant l'accès aux fichiers: createSyncAccessHandle()
(pour les opérations de lecture et d'écriture synchrones).
Il est exposé sur FileSystemFileHandle
, mais exclusivement dans
Nœuds de calcul Web
// (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 });
Polyremplissage
Il n'est pas possible de polyfill complètement les méthodes de l'API File System Access.
- La méthode
showOpenFilePicker()
peut être approximative avec un élément<input type="file">
. - La méthode
showSaveFilePicker()
peut être simulée avec un élément<a download="file_name">
. mais cela déclenche un téléchargement programmatique et ne permet pas d'écraser des fichiers existants. - La méthode
showDirectoryPicker()
peut être émulée avec l'API non standard Élément<input type="file" webkitdirectory>
.
Nous avons développé une bibliothèque appelée browser-fs-access qui utilise l'API l'API System Access autant que possible, et qui s'appuie sur ces meilleures options dans toutes les autres cas d'utilisation.
Sécurité et autorisations
L'équipe Chrome a conçu et mis en œuvre l'API File System Access selon les principes fondamentaux définies dans la section Contrôler l'accès à des fonctionnalités puissantes de plate-forme Web, y compris les règles le contrôle et la transparence, et l'ergonomie.
Ouvrir un fichier ou enregistrer un nouveau fichier
<ph type="x-smartling-placeholder">![Sélecteur de fichier pour ouvrir un fichier à lire](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-open-file-8cb5f6783ee89.jpg?authuser=1&hl=fr)
Lors de l'ouverture d'un fichier, l'utilisateur accorde l'autorisation de lire un fichier ou un répertoire à l'aide du sélecteur de fichier.
Le sélecteur de fichier ouvert ne peut s'afficher qu'à l'aide d'un geste de l'utilisateur lorsqu'il est diffusé depuis une interface sécurisée
le contexte. Si les utilisateurs changent d'avis, ils peuvent annuler la sélection dans le fichier.
et le site n'a accès à rien. Ce comportement est identique à celui de la
Élément <input type="file">
.
![Sélecteur de fichier pour enregistrer un fichier sur le disque.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-save-file-bd54ae001799a.jpg?authuser=1&hl=fr)
De même, lorsqu'une application Web souhaite enregistrer un nouveau fichier, le navigateur affiche le sélecteur d'enregistrement de fichier, permettant à l'utilisateur de spécifier le nom et l'emplacement du nouveau fichier. Puisqu'il enregistre un nouveau fichier à l'appareil (au lieu d'écraser un fichier existant), le sélecteur de fichier autorise l'application à écrire dans le fichier.
Dossiers restreints
Pour protéger les utilisateurs et leurs données, le navigateur peut limiter la capacité de l'utilisateur à enregistrer dans certaines tels que les dossiers du système d'exploitation comme Windows ou les dossiers de la bibliothèque macOS. Dans ce cas, le navigateur affiche une invite et demande à l'utilisateur de choisir une autre .
Modifier un fichier ou un répertoire existant
Une application Web ne peut pas modifier un fichier sur un disque sans obtenir l'autorisation explicite de l'utilisateur.
Invite concernant l'autorisation
Si une personne souhaite enregistrer les modifications apportées à un fichier auquel elle a précédemment accordé un accès en lecture, le navigateur affiche une invite d’autorisation, demandant l’autorisation pour le site d’écrire des modifications sur le disque. La demande d'autorisation ne peut être déclenchée que par un geste de l'utilisateur (par exemple, en cliquant sur un bouton .
<ph type="x-smartling-placeholder">![Une invite d'autorisation s'affiche avant l'enregistrement d'un fichier.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/permission-prompt-shown-p-823d180f97ad5.png?authuser=1&hl=fr)
Une appli Web qui modifie plusieurs fichiers, comme un IDE, peut aussi demander l'autorisation d'enregistrer les changements au moment de l’ouverture.
Si l'utilisateur choisit "Annuler" et n'accorde pas l'accès en écriture, l'application Web ne peut pas enregistrer les modifications fichier local. Elle doit fournir à l'utilisateur une autre méthode pour enregistrer ses données, par par exemple en permettant de "télécharger" le fichier ou l'enregistrement de données dans le cloud.
Transparence
<ph type="x-smartling-placeholder">![Icône de l'omnibox](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/omnibox-icon-5797e9a831603.jpg?authuser=1&hl=fr)
Une fois qu'un utilisateur a autorisé une application Web à enregistrer un fichier local, le navigateur affiche une icône dans la barre d'adresse. En cliquant sur l'icône, un pop-up s'ouvre et affiche la liste des fichiers fournis par l'utilisateur. y accéder. L'utilisateur peut toujours révoquer cet accès s'il le souhaite.
Persistance des autorisations
L'application Web peut continuer à enregistrer les modifications apportées au fichier sans afficher d'invite jusqu'à ce que tous les onglets de son sont fermées. Lorsqu'un onglet est fermé, le site perd tout accès. La prochaine fois que l'utilisateur utilisera l'application Web, il sera de nouveau invité à accéder aux fichiers.
Commentaires
Nous aimerions connaître votre avis sur votre expérience avec l'API File System Access.
Présentez-nous la conception de l'API
Y a-t-il un aspect de l'API qui ne fonctionne pas comme prévu ? Ou manque-t-il des méthodes ou les propriétés dont vous avez besoin pour mettre en œuvre votre idée ? Vous avez une question ou un commentaire sur la sécurité ?
- Faites une demande de spécifications dans le dépôt GitHub WICG File System Access ou donnez votre avis à un problème existant.
Vous rencontrez un problème lors de l'implémentation ?
Avez-vous détecté un bug dans l'implémentation de Chrome ? Ou l'implémentation est-elle différente des spécifications ?
- Signalez un bug sur https://new.crbug.com. Veillez à inclure autant
de détails que possible,
les instructions de reproduction et définissez Components sur
Blink>Storage>FileSystem
. Glitch est idéal pour partager des répétitions rapides.
Vous prévoyez d'utiliser l'API ?
Vous prévoyez d'utiliser l'API File System Access sur votre site ? Votre soutien public nous aide à prioriser et montre aux autres fournisseurs de navigateurs à quel point il est essentiel de les prendre en charge.
- Expliquez comment vous prévoyez de l'utiliser dans le fil de discussion du discours de WiCG.
- Envoyez un tweet à @ChromiumDev en utilisant le hashtag.
#FileSystemAccess
et n'hésitez pas à nous indiquer où et comment vous l'utilisez.
Liens utiles
- Explication publique
- Spécifications pour l'accès au système de fichiers Spécifications des fichiers
- Bug de suivi
- Entrée ChromeStatus.com
- Définitions TypeScript
- API File System Access – Modèle de sécurité Chromium
- Composant Blink:
Blink>Storage>FileSystem
Remerciements
La spécification de l'API File System Access a été écrite par Marijn Kruisselbrink