La API de File System Access permite que las aplicaciones web lean o guarden cambios directamente en archivos y carpetas del dispositivo del usuario.
¿Qué es la API de File System Access?
La API de File System Access permite a los desarrolladores compilar aplicaciones web potentes que interactúan con en el dispositivo local del usuario, como los IDE, los editores de fotos y videos, los editores de texto, etc. Después del cuando un usuario otorga acceso a una aplicación web, esta API le permite leer o guardar cambios directamente en los archivos y carpetas del dispositivo del usuario. Además de leer y escribir archivos, la API de File System Access proporciona permite abrir un directorio y enumerar su contenido.
Si ya trabajaste con la lectura y escritura de archivos, gran parte de lo que voy a compartir será que sean familiares para ti. Te recomiendo que lo leas de todas formas, ya que no todos los sistemas son iguales.
La API de File System Access es compatible con la mayoría de los navegadores Chromium en Windows, macOS, ChromeOS y Linux. Una notable excepción es Brave, donde es actualmente solo está disponible detrás de una marca. Se está trabajando en la compatibilidad con Android en el contexto de crbug.com/1011535.
Cómo usar la API de File System Access
Para mostrar la potencia y utilidad de la API de File System Access, escribí un solo archivo de texto Google Cloud. Te permite abrir un archivo de texto, editarlo, guardar los cambios en el disco o iniciar un archivo nuevo y guarda los cambios en el disco. No es nada sofisticado, pero es suficiente para ayudarte comprender los conceptos.
Navegadores compatibles
Detección de funciones
Para saber si se admite la API de File System Access, verifica si el método de selección que te interesa existe.
if ('showOpenFilePicker' in self) {
// The `showOpenFilePicker()` method of the File System Access API is supported.
}
Probar
Observa cómo funciona la API de File System Access en la editor de texto.
Lee un archivo desde el sistema de archivos local
El primer caso de uso que quiero abordar es pedirle al usuario que elija un archivo, luego abrirlo y leerlo desde el disco.
Pídele al usuario que elija un archivo para leerlo
El punto de entrada a la API de File System Access es
window.showOpenFilePicker()
Cuando se lo llama, muestra un diálogo de selector de archivos
y le pide al usuario que seleccione un archivo. Después de seleccionar un archivo, la API muestra un array de archivos
controladores. Un parámetro options
opcional te permite influir en el comportamiento del selector de archivos, para
por ejemplo, permitiendo que el usuario seleccione varios archivos, directorios o diferentes tipos de archivos.
Sin ninguna opción especificada, el selector de archivos permite al usuario seleccionar un solo archivo. Este es
perfecto para un editor de texto.
Al igual que muchas otras APIs potentes, la llamada a showOpenFilePicker()
debe realizarse en un entorno
contextual y se debe llamar desde un gesto del usuario.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});
Una vez que el usuario selecciona un archivo, showOpenFilePicker()
muestra un array de identificadores. En este caso, es un
array de un elemento con un FileSystemFileHandle
que contiene las propiedades y
métodos necesarios para interactuar con el archivo.
Es útil mantener una referencia al identificador del archivo para que pueda usarse más adelante. Será necesario para guardar los cambios en el archivo o para realizar cualquier otra operación relacionada.
Cómo leer un archivo desde el sistema de archivos
Ahora que tienes un controlador para un archivo, puedes obtener sus propiedades o acceder a él.
Por ahora, leeré su contenido. Si llamas a handle.getFile()
, se muestra un File
.
que contiene un BLOB. Para obtener datos del BLOB, llama a uno de sus
métodos, (slice()
,
stream()
,
text()
o
arrayBuffer()
).
const file = await fileHandle.getFile();
const contents = await file.text();
El objeto File
que muestra FileSystemFileHandle.getFile()
solo se puede leer siempre que el elemento
el archivo subyacente del disco no haya cambiado. Si se modifica el archivo del disco, el objeto File
se convierte en
no se puede leer y deberás volver a llamar a getFile()
para obtener un nuevo objeto File
que lea el cambio
de datos no estructurados.
Revisión general
Cuando los usuarios hacen clic en el botón Open, el navegador muestra un selector de archivos. Una vez que hayan seleccionado un archivo,
La app lee el contenido y lo coloca en 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;
});
Escribe el archivo en el sistema de archivos local
En el editor de texto, hay dos formas de guardar un archivo: Guardar y Guardar como. Guardar vuelve a escribir los cambios en el archivo original con el controlador de archivo que se recuperó antes. Pero guarde Como crea un archivo nuevo y, por lo tanto, requiere un nuevo controlador de archivo.
Crea un archivo nuevo
Para guardar un archivo, llama a showSaveFilePicker()
, que muestra el selector de archivos.
en "Guardar" que le permite al usuario seleccionar un archivo nuevo que quiera usar para guardar. Para el texto
editor, también quería que agregara automáticamente una extensión .txt
, así que proporcioné algunas extensiones
parámetros.
async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}
Guardar cambios en el disco
Puedes encontrar todo el código para guardar cambios en un archivo en mi demostración del editor de texto en
GitHub: Las interacciones del sistema de archivos principal
fs-helpers.js
En pocas palabras, el proceso es similar al siguiente código:
Voy a repasar cada paso y lo explicaré.
// 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();
}
Escribir datos en el disco usa un objeto FileSystemWritableFileStream
, una subclase
de WritableStream
. Para crear la transmisión, llama a createWritable()
en el archivo.
objeto de controlador. Cuando se llama a createWritable()
, el navegador primero verifica si el usuario otorgó
permiso de escritura en el archivo. Si no se otorgó permiso de escritura, el navegador solicita
al usuario para obtener el permiso. Si no se otorga permiso, createWritable()
arroja un
DOMException
y la app no podrá escribir en el archivo. En el editor de texto,
Los objetos DOMException
se controlan en el método saveFile()
.
El método write()
toma una cadena, que es lo que se necesita para un editor de texto. Pero también puede tardar
una BufferSource o un Blob. Por ejemplo, puedes canalizar una transmisión directamente a
de la siguiente manera:
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.
}
También puedes seek()
o truncate()
en la transmisión para actualizar la
archivo en una posición específica o cambiar su tamaño.
Especifica un nombre de archivo y un directorio de inicio sugeridos
En muchos casos, es posible que desees que tu app sugiera un nombre de archivo o ubicación predeterminados. Por ejemplo, un texto
es posible que quieras sugerir un nombre de archivo predeterminado de Untitled Text.txt
en lugar de Untitled
. Tú
Para lograrlo, pasa una propiedad suggestedName
como parte de las opciones de showSaveFilePicker
.
const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});
Lo mismo ocurre con el directorio de inicio predeterminado. Si estás creando un editor de texto, te recomendamos
comenzará el diálogo para guardar o abrir el archivo en la carpeta predeterminada documents
, mientras que para una imagen
editor, es posible que desees comenzar en la carpeta predeterminada pictures
. Puedes sugerir un inicio predeterminado
de directorio si pasas una propiedad startIn
a showSaveFilePicker
, showDirectoryPicker()
o
showOpenFilePicker
. Así.
const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});
Esta es la lista de los directorios del sistema conocidos:
desktop
: Es el directorio del escritorio del usuario, en caso de que exista.documents
: Directorio en el que se suelen almacenar los documentos que crea el usuario.downloads
: Directorio en el que se almacenarán los archivos descargados por lo general.music
: Directorio en el que se almacenarán los archivos de audio por lo general.pictures
: Directorio en el que se suelen almacenar las fotos y otras imágenes estáticas.videos
: Directorio donde se almacenarán los videos o las películas por lo general.
Además de los directorios del sistema conocidos, también puedes pasar un controlador de directorio o archivo existente como
un valor para startIn
El diálogo se abrirá en el mismo directorio.
// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});
Cómo especificar el propósito de diferentes selectores de archivos
A veces, las aplicaciones tienen diferentes selectores para distintos fines. Por ejemplo, un texto enriquecido
puede permitir que el usuario abra archivos de texto y también importe imágenes. De forma predeterminada, cada archivo
el selector se abrirá en la última ubicación recordada. Para evitar esto, almacena valores de id
para cada tipo de selector. Si se especifica un id
, la implementación del selector de archivos recordará un
y el último directorio usado para ese id
.
const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});
const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});
Almacena controladores de archivos o directorios en IndexedDB
Los controladores de archivos y directorios se pueden serializar, lo que significa que puedes guardar un archivo o
el controlador de directorio a IndexedDB, o bien llamar a postMessage()
para enviarlas entre el mismo nivel superior
origen.
Guardar controladores de archivos o directorios en IndexedDB significa que puedes almacenar el estado o recordar qué o directorios en los que trabajaba un usuario. Esto permite mantener una lista de los correos electrónicos abiertos o editados, ofrecer la posibilidad de volver a abrir el último archivo cuando se abra la aplicación, restablecer el trabajo anterior directorio y mucho más. En el editor de texto, almaceno una lista de los cinco archivos más recientes que tiene el usuario. abierto, lo que posibilita el acceso a esos archivos nuevamente.
En el siguiente ejemplo de código, se muestra cómo almacenar y recuperar un controlador de archivo y un controlador de directorio. Puedes mira esto en acción en Glitch. (Uso la biblioteca idb-keyval para abreviar).
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);
}
});
Identificadores y permisos de archivos o directorios almacenados
Dado que los permisos no siempre persisten entre sesiones, debes verificar si el usuario
otorgó permiso al archivo o directorio con queryPermission()
. Si no lo hizo, llama
requestPermission()
para (volver a) solicitarla. Esto funciona de la misma manera para los controladores de archivos y directorios. Tú
debes ejecutar fileOrDirectoryHandle.requestPermission(descriptor)
o
fileOrDirectoryHandle.queryPermission(descriptor)
respectivamente.
En el editor de texto, creé un método verifyPermission()
que verifica si el usuario ya
el permiso otorgado y, si es necesario, realiza la solicitud.
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;
}
Al solicitar permiso de escritura con la solicitud de lectura, reduje la cantidad de solicitudes de permiso. el usuario ve un mensaje cuando abre el archivo y le otorga permiso de lectura y escritura.
Abrir un directorio y enumerar su contenido
Para enumerar todos los archivos de un directorio, llama a showDirectoryPicker()
. El usuario
selecciona un directorio en un selector, después de lo cual se agrega un FileSystemDirectoryHandle
que se muestra, lo que te permite enumerar los archivos del directorio y acceder a ellos. De forma predeterminada, habrás leído
acceso a los archivos del directorio, pero si necesitas acceso de escritura, puedes pasar
{ mode: 'readwrite' }
al método
butDir.addEventListener('click', async () => {
const dirHandle = await window.showDirectoryPicker();
for await (const entry of dirHandle.values()) {
console.log(entry.kind, entry.name);
}
});
Si además necesitas acceder a cada archivo con getFile()
para, por ejemplo, obtener la persona
tamaños de archivos, no uses await
en cada resultado de forma secuencial; procesa todos los archivos en
paralelo, por ejemplo, con 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));
});
Crea archivos y carpetas en un directorio o accede a ellos
Desde un directorio, puedes crear o acceder a archivos y carpetas con el
getFileHandle()
o, respectivamente, getDirectoryHandle()
. Pasa un objeto options
opcional con una clave de create
y un valor booleano de
true
o false
, puedes determinar si se debe crear un archivo o una carpeta nuevos en caso de que no existan.
// 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 });
Resuelve la ruta de acceso de un elemento en un directorio
Cuando trabajas con archivos o carpetas en un directorio, puede ser útil resolver la ruta de acceso del elemento
en cuestión. Esto se puede hacer con el método resolve()
, que es el nombre correcto. Para la resolución,
El elemento puede ser un elemento secundario directo o indirecto del directorio.
// 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"]
Borra archivos y carpetas en un directorio
Si obtuviste acceso a un directorio, puedes borrar los archivos y carpetas contenidos con el
removeEntry()
. En el caso de las carpetas, la eliminación puede ser recursiva y se incluye
todas las subcarpetas y los archivos que contiene.
// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
Cómo borrar un archivo o una carpeta directamente
Si tienes acceso a un controlador de directorio o archivo, llama a remove()
en un objeto FileSystemFileHandle
.
FileSystemDirectoryHandle
para quitarlo.
// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();
Cómo cambiar el nombre de archivos y carpetas y moverlos
Para cambiar el nombre de los archivos y las carpetas o moverlos a una nueva ubicación, llama a move()
en el
FileSystemHandle
. FileSystemHandle
tiene las interfaces secundarias FileSystemFileHandle
y
FileSystemDirectoryHandle
El método move()
toma uno o dos parámetros. La primera puede
ser una cadena con el nombre nuevo o un FileSystemDirectoryHandle
a la carpeta de destino. En la
último caso, el segundo parámetro opcional es una cadena con el nuevo nombre, por lo que mover y cambiar el nombre puede
en un solo paso.
// 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');
Integración de arrastrar y soltar
El
Interfaces HTML de arrastrar y soltar
para que las aplicaciones web acepten
archivos arrastrados y soltados
en una página web. Durante una operación de arrastrar y soltar, los elementos de archivos y directorios arrastrados se asocian
con entradas de archivos y entradas de directorio, respectivamente. El DataTransferItem.getAsFileSystemHandle()
muestra una promesa con un objeto FileSystemFileHandle
si el elemento arrastrado es un archivo y un
con un objeto FileSystemDirectoryHandle
si el elemento arrastrado es un directorio. El siguiente listado
muestra esto en acción. Ten en cuenta que la interfaz de arrastrar y soltar
DataTransferItem.kind
es
"file"
para archivos y directorios, mientras que FileSystemHandle.kind
de la API de File System Access se usa
"file"
para archivos y "directory"
para directorios.
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}`);
}
}
});
Accede al sistema de archivos privados de origen
El sistema de archivos privados de origen es un extremo de almacenamiento que, como su nombre lo indica, es privado para el
el origen de la página. Si bien los navegadores suelen implementar esto
con la persistencia del contenido de este
desde el sistema de archivos privados de origen al disco, no está previsto que los contenidos
accesible. Asimismo, no se espera que los archivos o directorios con nombres que coincidan con
existen los nombres de los elementos secundarios del sistema de archivos privados de origen. Si bien es posible que el navegador parezca que
hay archivos internamente. Ya que se trata de un sistema de origen de archivos privados, el navegador puede almacenar
estos "archivos" en una base de datos o en cualquier otra estructura de datos. Básicamente, si usas esta API,
No esperes encontrar los archivos creados que coincidan uno a uno en algún lugar del disco duro. Puedes operar como de costumbre en
el sistema de archivos privados de origen una vez que tengas acceso a la raíz 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 });
Cómo acceder a archivos optimizados para el rendimiento desde el sistema de archivos privados de origen
El sistema de archivos privados de origen proporciona acceso opcional a un tipo especial de archivo que es muy
para optimizar el rendimiento, por ejemplo, ofreciendo acceso de escritura in situ y exclusivo a la
contenido. En Chromium 102 y versiones posteriores, existe un método adicional en el sistema de archivos privados de origen para
lo que simplifica el acceso al archivo: createSyncAccessHandle()
(para operaciones de lectura y escritura síncronas).
Se expone en FileSystemFileHandle
, pero exclusivamente en
Trabajadores 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 });
Polyfill
No es posible rellenar por completo los métodos de la API de File System Access.
- El método
showOpenFilePicker()
se puede aproximar con un elemento<input type="file">
. - El método
showSaveFilePicker()
se puede simular con un elemento<a download="file_name">
, pero esto activa una descarga programática y no permite reemplazar archivos existentes. - El método
showDirectoryPicker()
se puede emular de alguna manera con el método elemento<input type="file" webkitdirectory>
.
Desarrollamos una biblioteca llamada browser-fs-access que usa API de Acceso al sistema siempre que sea posible y que recurra a estas mejores opciones en todas las demás diferentes.
Seguridad y permisos
El equipo de Chrome diseñó e implementó la API de File System Access usando los principios básicos se definen en Controla el acceso a las funciones potentes de la plataforma web, incluida la información para garantizar el control y la transparencia y la ergonomía de los usuarios.
Abrir un archivo o guardar uno nuevo
![Selector de archivos para abrir un archivo para leerlo](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-open-file-8cb5f6783ee89.jpg?authuser=0000&hl=es)
Cuando el usuario abre un archivo, otorga permiso para leer un archivo o directorio con el selector de archivos.
El selector de archivos abierto solo se puede mostrar con un gesto del usuario cuando se entrega desde un servidor
contextual. Si los usuarios cambian de opinión, pueden cancelar la selección en el archivo.
y el sitio no tendrá acceso a nada. Este es el mismo comportamiento que el de la
<input type="file">
.
![Selector de archivos para guardar un archivo en el disco.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/file-picker-save-file-bd54ae001799a.jpg?authuser=0000&hl=es)
Del mismo modo, cuando una aplicación web quiere guardar un archivo nuevo, el navegador muestra el selector para guardar archivos, lo que le permite al usuario especificar el nombre y la ubicación del archivo nuevo. Dado que está guardando un archivo nuevo al dispositivo (en lugar de reemplazar un archivo existente), el selector de archivos le otorga permiso a la aplicación escribir en el archivo.
Carpetas restringidas
Para ayudar a proteger a los usuarios y sus datos, el navegador puede limitar la capacidad del usuario de guardar contenido en ciertos por ejemplo, las principales del sistema operativo, como Windows, y las carpetas Biblioteca de macOS. Cuando esto sucede, el navegador muestra un mensaje y le pide al usuario que elija un cambio carpeta.
Cómo modificar un archivo o directorio existente
Una app web no puede modificar un archivo en el disco sin obtener el permiso explícito del usuario.
Solicitud de permiso
Si una persona quiere guardar los cambios realizados en un archivo al que previamente le concedió acceso de lectura, el navegador muestra un mensaje de solicitud de permiso para que el sitio escriba cambios en el disco. La solicitud de permiso solo se puede activar con un gesto del usuario, por ejemplo, haciendo clic en un botón para Guardar .
![El mensaje de permiso se muestra antes de guardar un archivo.](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/permission-prompt-shown-p-823d180f97ad5.png?authuser=0000&hl=es)
Como alternativa, una aplicación web que edita varios archivos, como un IDE, también puede solicitar permiso para guardar. cambios en el momento de la apertura.
Si el usuario elige Cancelar y no otorga acceso de escritura, la aplicación web no podrá guardar los cambios en la archivo local. Debe proporcionar un método alternativo para que el usuario guarde sus datos, de ejemplo, proporcionando una forma de "descargar" en el archivo o guardar datos en la nube.
Transparencia
![Ícono del cuadro multifunción](https://developer.chrome.google.cn/static/docs/capabilities/web-apis/file-system-access/image/omnibox-icon-5797e9a831603.jpg?authuser=0000&hl=es)
Una vez que un usuario otorga permiso a una app web para guardar un archivo local, el navegador muestra un ícono en la barra de direcciones. Si se hace clic en el ícono, se abrirá una ventana emergente con la lista de archivos que proporcionó el usuario. a los que tienes acceso. El usuario siempre puede revocar ese acceso si lo desea.
Persistencia de permisos
La aplicación web puede seguir guardando los cambios en el archivo sin preguntar hasta que todas las pestañas el origen está cerrado. Una vez que se cierra una pestaña, el sitio pierde todo el acceso. La próxima vez que el usuario use se le volverá a solicitar acceso a los archivos.
Comentarios
Nos gustaría conocer tu experiencia con la API de File System Access.
Cuéntanos sobre el diseño de la API
¿Algo en la API no funciona como esperabas? ¿O faltan métodos o propiedades que necesitas para implementar tu idea? Haz una pregunta o comentario sobre la seguridad modelo?
- Informa un problema de especificaciones en el repositorio de GitHub de Acceso al sistema de archivos de WICG o agrega lo que piensas. a un problema existente.
¿Tiene problemas con la implementación?
¿Encontraste un error en la implementación de Chrome? ¿O la implementación es diferente de la especificación?
- Informa un error en https://new.crbug.com. Asegúrate de incluir tantos detalles como puedas
y establece Components en
Blink>Storage>FileSystem
. Glitch funciona muy bien para compartir repros rápidos.
¿Piensas usar la API?
¿Piensas usar la API de File System Access en tu sitio? Tu apoyo público nos ayuda a priorizar y muestra a otros proveedores de navegadores la importancia de admitirlas.
- Comparte cómo piensas usarlo en la conversación del discurso de WICG.
- Envía un tweet a @ChromiumDev con el hashtag
#FileSystemAccess
y cuéntanos dónde y cómo lo utilizas.
Vínculos útiles
- Explicación pública
- Especificación de acceso al sistema de archivos y Especificación del archivo
- Seguimiento de errores
- Entrada de ChromeStatus.com
- Definiciones de TypeScript
- API de File System Access: Modelo de seguridad de Chromium
- Componente de parpadeo:
Blink>Storage>FileSystem
Agradecimientos
La especificación de la API de File System Access fue escrita por Marijn Kruisselbrink.