A API File System Access permite que os apps da Web leiam ou salvem alterações diretamente em arquivos e pastas no dispositivo do usuário.
O que é a API File System Access?
A API File System Access (anteriormente conhecida como API Native File System e, antes disso, era chamada de API Writeable Files) permite que os desenvolvedores criem apps da Web avançados que interagem com arquivos no dispositivo local do usuário, como ambientes de desenvolvimento integrado, editores de fotos e vídeos, editores de texto e muito mais. Depois que um usuário concede acesso a um app da Web, essa API permite que ele leia ou salve mudanças diretamente em arquivos e pastas no dispositivo do usuário. Além de ler e gravar arquivos, a API File System Access permite abrir um diretório e enumerar o conteúdo dele.
Se você já trabalhou com leitura e gravação de arquivos antes, muitos do que vou compartilhar será familiar para você. Recomendo que você leia mesmo assim, porque nem todos os sistemas são iguais.
No momento, a API File System Access tem suporte à maioria dos navegadores Chromium no Windows, macOS, ChromeOS e Linux. Uma exceção importante é a Brave, em que ele está atualmente disponível apenas por trás de uma flag. O Android oferece suporte à parte do sistema de arquivos privados de origem da API desde o Chromium 109. No momento, não há planos para os métodos do seletor, mas é possível acompanhar o possível progresso ao marcar com estrela crbug.com/1011535 (link em inglês).
Como usar a API File System Access
Para mostrar o poder e a utilidade da API File System Access, criei um único editor de texto de arquivo. Ele permite abrir um arquivo de texto, editá-lo, salvar as alterações em disco ou iniciar um novo arquivo e salvar as alterações no disco. Não é nada sofisticado, mas fornece o suficiente para ajudar você a entender os conceitos.
Suporte ao navegador
Testar
Confira a API File System Access em ação na demonstração do editor de texto.
Ler um arquivo do sistema de arquivos local
O primeiro caso de uso que quero abordar é pedir que o usuário escolha um arquivo e abra e leia esse arquivo do disco.
Pedir que o usuário escolha um arquivo para ler
O ponto de entrada para a API File System Access é
window.showOpenFilePicker()
. Quando chamado, ele mostra uma caixa de diálogo do seletor de arquivos
e solicita que o usuário selecione um arquivo. Depois que um arquivo é selecionado, a API retorna uma matriz de identificadores de arquivos. Um parâmetro options
opcional permite influenciar o comportamento do seletor de arquivos, por
exemplo, permitindo que o usuário selecione vários arquivos, diretórios ou tipos de arquivo diferentes.
Sem opções especificadas, o seletor de arquivos permite que o usuário selecione um único arquivo. Isso é
perfeito para um editor de texto.
Como muitas outras APIs avançadas, a chamada de showOpenFilePicker()
precisa ser feita em um contexto
seguro e ser chamada de um gesto do usuário.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
// Destructure the one-element array.
[fileHandle] = await window.showOpenFilePicker();
// Do something with the file handle.
});
Depois que o usuário seleciona um arquivo, showOpenFilePicker()
retorna uma matriz de identificadores. Nesse caso, uma
matriz de um elemento com um FileSystemFileHandle
que contém as propriedades e
os métodos necessários para interagir com o arquivo.
Vale a pena manter uma referência ao identificador de arquivo para que possa ser usada mais tarde. Ela será necessária para salvar as alterações no arquivo ou para executar qualquer outra operação dele.
Ler um arquivo do sistema de arquivos
Agora que você tem um identificador para um arquivo, pode obter as propriedades do arquivo ou acessar o próprio arquivo.
Por enquanto, vou simplesmente ler o conteúdo. Chamar handle.getFile()
retorna um objeto File
, que contém um blob. Para receber os dados do blob, chame um dos métodos
dele (slice()
,
stream()
,
text()
ou
arrayBuffer()
).
const file = await fileHandle.getFile();
const contents = await file.text();
O objeto File
retornado por FileSystemFileHandle.getFile()
só será legível se o
arquivo subjacente no disco não tiver sido modificado. Se o arquivo em disco for modificado, o objeto File
vai ficar ilegível, e você vai precisar chamar getFile()
novamente para que um novo objeto File
leia os dados alterados.
Para resumir
Quando os usuários clicam no botão "Abrir", o navegador mostra um seletor de arquivos. Depois de selecionar um arquivo, o
app lê o conteúdo e o coloca em um <textarea>
.
let fileHandle;
butOpenFile.addEventListener('click', async () => {
[fileHandle] = await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
textArea.value = contents;
});
Gravar o arquivo no sistema de arquivos local
No editor de texto, há duas maneiras de salvar um arquivo: Salvar e Salvar como. Salvar simplesmente grava as alterações no arquivo original usando o identificador de arquivo recuperado anteriormente. No entanto, Salvar como cria um novo arquivo e, portanto, exige um novo identificador de arquivo.
Criar um novo arquivo
Para salvar um arquivo, chame showSaveFilePicker()
, que mostra o seletor de arquivos
no modo "salvar", permitindo que o usuário escolha um novo arquivo que queira usar para salvar. Para o editor de texto, eu também queria adicionar automaticamente uma extensão .txt
, então forneci alguns parâmetros adicionais.
async function getNewFileHandle() {
const options = {
types: [
{
description: 'Text Files',
accept: {
'text/plain': ['.txt'],
},
},
],
};
const handle = await window.showSaveFilePicker(options);
return handle;
}
Salvar alterações no disco
O código para salvar mudanças em um arquivo está disponível na minha demonstração do editor de texto no
GitHub (em inglês). As principais interações do sistema de arquivos estão em
fs-helpers.js
. De modo mais simples, o processo é semelhante ao código abaixo.
Vou examinar cada etapa e explicá-la.
// 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();
}
A gravação de dados no disco usa um objeto FileSystemWritableFileStream
, uma subclasse
de WritableStream
. Crie o stream chamando createWritable()
no objeto de identificador do arquivo. Quando createWritable()
é chamado, o navegador verifica primeiro se o usuário concedeu
permissão de gravação ao arquivo. Se a permissão de gravação não tiver sido concedida, o navegador solicitará
a permissão do usuário. Se a permissão não for concedida, o createWritable()
vai gerar uma
DOMException
, e o app não poderá gravar no arquivo. No editor de texto, os
objetos DOMException
são processados no método saveFile()
.
O método write()
usa uma string, que é necessária para um editor de texto. Mas ela também pode usar
um BufferSource ou Blob. Por exemplo, é possível canalizar um stream diretamente para
ele:
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.
}
Você também pode usar seek()
ou truncate()
no stream para atualizar o
arquivo em uma posição específica ou redimensioná-lo.
Especificar um nome de arquivo e um diretório inicial sugeridos
Em muitos casos, você pode querer que seu app sugira um nome de arquivo ou local padrão. Por exemplo, um editor
de texto pode sugerir um nome de arquivo padrão de Untitled Text.txt
em vez de Untitled
. Para
fazer isso, transmita uma propriedade suggestedName
como parte das opções showSaveFilePicker
.
const fileHandle = await self.showSaveFilePicker({
suggestedName: 'Untitled Text.txt',
types: [{
description: 'Text documents',
accept: {
'text/plain': ['.txt'],
},
}],
});
O mesmo vale para o diretório inicial padrão. Se você estiver criando um editor de texto, recomendamos
iniciar a caixa de diálogo para salvar o arquivo ou abrir o arquivo na pasta documents
padrão. Para um editor
de imagens, comece na pasta pictures
padrão. Você pode sugerir um diretório inicial
padrão transmitindo uma propriedade startIn
para os métodos showSaveFilePicker
, showDirectoryPicker()
ou
showOpenFilePicker
.
const fileHandle = await self.showOpenFilePicker({
startIn: 'pictures'
});
A lista dos diretórios de sistema conhecidos é:
desktop
: o diretório da área de trabalho do usuário, se houver.documents
: diretório em que os documentos criados pelo usuário geralmente são armazenados.downloads
: diretório onde os arquivos transferidos por download normalmente seriam armazenados.music
: diretório em que os arquivos de áudio normalmente são armazenados.pictures
: diretório onde fotos e outras imagens estáticas normalmente seriam armazenadas.videos
: diretório onde os vídeos/filmes normalmente seriam armazenados.
Além dos diretórios do sistema conhecidos, você também pode passar um arquivo ou identificador de diretório já existente como
um valor para startIn
. A caixa de diálogo será aberta no mesmo diretório.
// Assume `directoryHandle` is a handle to a previously opened directory.
const fileHandle = await self.showOpenFilePicker({
startIn: directoryHandle
});
Como especificar a finalidade de diferentes seletores de arquivos
Às vezes, os aplicativos têm seletores diferentes para finalidades distintas. Por exemplo, um editor de rich text
pode permitir que o usuário abra arquivos de texto, mas também possa importar imagens. Por padrão, cada seletor de arquivo seria aberto no último local lembrado. É possível contornar isso armazenando valores id
para cada tipo de seletor. Se um id
for especificado, a implementação do seletor de arquivos vai se lembrar de um
diretório separado pelo último uso para esse id
.
const fileHandle1 = await self.showSaveFilePicker({
id: 'openText',
});
const fileHandle2 = await self.showSaveFilePicker({
id: 'importImage',
});
Armazenamento de identificadores de arquivos ou de diretórios no IndexedDB
Os gerenciadores de arquivos e de diretório são serializáveis, o que significa que é possível salvar um arquivo ou
de diretório no IndexedDB ou chamar postMessage()
para enviá-los entre a mesma origem de
nível superior.
Salvar identificadores de arquivo ou diretório no IndexedDB significa que você pode armazenar o estado ou lembrar em quais arquivos ou diretórios um usuário estava trabalhando. Isso possibilita manter uma lista de arquivos abertos ou editados recentemente, oferecer a opção de reabrir o último arquivo quando o app for aberto, restaurar o diretório de trabalho anterior e muito mais. No editor de texto, armazeno uma lista dos cinco arquivos mais recentes que o usuário abriu, facilitando o acesso a eles novamente.
O exemplo de código abaixo mostra como armazenar e recuperar um identificador de arquivo e um identificador de diretório. Confira isso em ação no Glitch. Para simplificar, uso a biblioteca idb-keyval.
import { get, set } from 'https://unpkg.com/idb-keyval@5.0.2/dist/esm/index.js';
const pre1 = document.querySelector('pre.file');
const pre2 = document.querySelector('pre.directory');
const button1 = document.querySelector('button.file');
const button2 = document.querySelector('button.directory');
// File handle
button1.addEventListener('click', async () => {
try {
const fileHandleOrUndefined = await get('file');
if (fileHandleOrUndefined) {
pre1.textContent = `Retrieved file handle "${fileHandleOrUndefined.name}" from IndexedDB.`;
return;
}
const [fileHandle] = await window.showOpenFilePicker();
await set('file', fileHandle);
pre1.textContent = `Stored file handle for "${fileHandle.name}" in IndexedDB.`;
} catch (error) {
alert(error.name, error.message);
}
});
// Directory handle
button2.addEventListener('click', async () => {
try {
const directoryHandleOrUndefined = await get('directory');
if (directoryHandleOrUndefined) {
pre2.textContent = `Retrieved directroy handle "${directoryHandleOrUndefined.name}" from IndexedDB.`;
return;
}
const directoryHandle = await window.showDirectoryPicker();
await set('directory', directoryHandle);
pre2.textContent = `Stored directory handle for "${directoryHandle.name}" in IndexedDB.`;
} catch (error) {
alert(error.name, error.message);
}
});
Permissões e identificadores de arquivos ou diretórios armazenados
Como as permissões atualmente não são mantidas entre as sessões, verifique se o usuário
concedeu permissão ao arquivo ou diretório usando queryPermission()
. Caso contrário, chame requestPermission()
para solicitá-lo novamente. Isso funciona da mesma forma para identificadores de arquivos e diretórios. Você
precisa executar fileOrDirectoryHandle.requestPermission(descriptor)
ou
fileOrDirectoryHandle.queryPermission(descriptor)
, respectivamente.
No editor de texto, criei um método verifyPermission()
que verifica se o usuário já
concedeu a permissão e, se necessário, faz a solicitação.
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;
}
Ao solicitar a permissão de gravação com a solicitação de leitura, reduzimos o número de solicitações de permissão. O usuário vê uma solicitação ao abrir o arquivo e concede permissão para leitura e gravação.
Como abrir um diretório e enumerar seu conteúdo
Para enumerar todos os arquivos em um diretório, chame showDirectoryPicker()
. O usuário
seleciona um diretório em um seletor. Depois disso, uma FileSystemDirectoryHandle
é
retornada, que permite enumerar e acessar os arquivos do diretório. Por padrão, você terá acesso de leitura aos arquivos no diretório, mas, se precisar de acesso de gravação, poderá passar { mode: 'readwrite' }
para o método.
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 você também precisar acessar cada arquivo via getFile()
para, por exemplo, conseguir os tamanhos
de arquivos individuais, não use await
em cada resultado sequencialmente. Em vez disso, processe todos os arquivos em
paralelo, por exemplo, usando 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));
});
Criar ou acessar arquivos e pastas em um diretório
Em um diretório, é possível criar ou acessar arquivos e pastas usando o
getFileHandle()
ou, respectivamente, o método
getDirectoryHandle()
. Ao transmitir um objeto options
opcional com uma chave de create
e um valor booleano de
true
ou false
, você pode determinar se um novo arquivo ou pasta precisa ser criado, se não existir.
// 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 });
Resolver o caminho de um item em um diretório
Ao trabalhar com arquivos ou pastas em um diretório, pode ser útil resolver o caminho do item
em questão. Isso pode ser feito com o método resolve()
adequadamente chamado. Para resolver, o
item pode ser um filho direto ou indireto do diretório.
// 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"]
Como excluir arquivos e pastas de um diretório
Se você tiver acesso a um diretório, exclua os arquivos e as pastas contidos nele com o
método removeEntry()
. Para pastas, a exclusão pode ser recursiva e incluir
todas as subpastas e os arquivos contidos nelas.
// Delete a file.
await directoryHandle.removeEntry('Abandoned Projects.txt');
// Recursively delete a folder.
await directoryHandle.removeEntry('Old Stuff', { recursive: true });
Excluir um arquivo ou uma pasta diretamente
Se você tiver acesso a um identificador de arquivo ou diretório, chame remove()
em um FileSystemFileHandle
ou
FileSystemDirectoryHandle
para removê-lo.
// Delete a file.
await fileHandle.remove();
// Delete a directory.
await directoryHandle.remove();
Como renomear e mover arquivos e pastas
Para renomear ou mover arquivos e pastas para um novo local, chame move()
na
interface FileSystemHandle
. FileSystemHandle
tem as interfaces filhas FileSystemFileHandle
e
FileSystemDirectoryHandle
. O método move()
usa um ou dois parâmetros. O primeiro pode
ser uma string com o novo nome ou um FileSystemDirectoryHandle
para a pasta de destino. No
último caso, o segundo parâmetro opcional é uma string com o novo nome. Portanto, a movimentação e renomeação podem
acontecer em uma única etapa.
// 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');
Integração de arrastar e soltar
As
interfaces HTML de arrastar e soltar
permitem que os aplicativos da Web aceitem
arquivos arrastados e soltos
em uma página da Web. Durante uma operação de arrastar e soltar, os itens de arquivo e diretório arrastados são associados
a entradas de arquivo e de diretório, respectivamente. O método DataTransferItem.getAsFileSystemHandle()
retornará uma promessa com um objeto FileSystemFileHandle
se o item arrastado for um arquivo, e uma
promessa com um objeto FileSystemDirectoryHandle
se o item arrastado for um diretório. A listagem abaixo mostra isso em ação. Observe que o DataTransferItem.kind
da interface de arrastar e soltar é
"file"
para arquivos e diretórios, enquanto o
FileSystemHandle.kind
da API File System Access é
"file"
para arquivos e "directory"
para diretórios.
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}`);
}
}
});
Como acessar o sistema de arquivos privados de origem
O sistema de arquivos privados de origem é um endpoint de armazenamento que, como o nome sugere, é particular para a
origem da página. Embora os navegadores geralmente implementem isso mantendo o conteúdo desse
sistema de arquivos particular de origem em algum lugar no disco, não se destina que o conteúdo seja facilmente acessível ao
usuário. Da mesma forma, não é esperado que existam arquivos ou diretórios com nomes correspondentes aos
nomes dos filhos do sistema de arquivos particular de origem. Embora o navegador possa fazer parecer que
há arquivos, internamente, já que esse é um sistema de arquivos de origem particular, ele pode armazenar
esses "arquivos" em um banco de dados ou em qualquer outra estrutura de dados. Se você usar essa API, não espere encontrar os arquivos criados com correspondência um para um em algum lugar do disco rígido. Você poderá operar normalmente no
sistema de arquivos particular de origem quando tiver acesso à raiz 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 });
Acessar arquivos otimizados para desempenho do sistema de arquivos particular de origem
O sistema de arquivos privados de origem oferece acesso opcional a um tipo especial de arquivo altamente
otimizado para desempenho, por exemplo, oferecendo acesso de gravação exclusivo e no local ao conteúdo
de um arquivo. No Chromium 102 e versões mais recentes, há um outro método no sistema de arquivos privados de origem para
simplificar o acesso a arquivos: createSyncAccessHandle()
, para operações síncronas de leitura e gravação.
Ele é exposto em FileSystemFileHandle
, mas exclusivamente em
Web Workers.
// (Read and write operations are synchronous,
// but obtaining the handle is asynchronous.)
// Synchronous access exclusively in Worker contexts.
const accessHandle = await fileHandle.createSyncAccessHandle();
const writtenBytes = accessHandle.write(buffer);
const readBytes = accessHandle.read(buffer, { at: 1 });
Polipreenchimento
Não é possível aplicar polyfill a todos os métodos da API File System Access.
- O método
showOpenFilePicker()
pode ser aproximado com um elemento<input type="file">
. - O método
showSaveFilePicker()
pode ser simulado com um elemento<a download="file_name">
, embora isso acione um download programático e não permita a substituição de arquivos atuais. - O método
showDirectoryPicker()
pode ser emulado de alguma forma com o elemento<input type="file" webkitdirectory>
não padrão.
Desenvolvemos uma biblioteca chamada browser-fs-access que usa a API File System Access sempre que possível e que usa as próximas melhores opções em todos os casos.
Segurança e permissões
A equipe do Chrome projetou e implementou a API File System Access usando os princípios fundamentais definidos em Como controlar o acesso a recursos avançados da plataforma da Web, incluindo controle e transparência do usuário e ergonomia do usuário.
Abrir ou salvar um arquivo
![Seletor de arquivos para abrir um arquivo para leitura](https://developer.chrome.com/static/docs/capabilities/web-apis/file-system-access/image/file-picker-open-file-8cb5f6783ee89.jpg?authuser=6&hl=pt)
Ao abrir um arquivo, o usuário concede permissão para ler um arquivo ou diretório por meio do seletor de arquivos.
O seletor aberto de arquivos só pode ser exibido com um gesto do usuário quando veiculado de um contexto
seguro. Se os usuários mudarem de ideia, eles podem cancelar a seleção no seletor de arquivos e o site não terá acesso a nada. Esse é o mesmo comportamento do elemento
<input type="file">
.
![Seletor de arquivos para salvar um arquivo em disco.](https://developer.chrome.com/static/docs/capabilities/web-apis/file-system-access/image/file-picker-save-file-bd54ae001799a.jpg?authuser=6&hl=pt)
Da mesma forma, quando um app da Web quer salvar um novo arquivo, o navegador mostra o seletor para salvar arquivos, permitindo que o usuário especifique o nome e o local do novo arquivo. Como eles estão salvando um novo arquivo no dispositivo (em vez de substituir um arquivo existente), o seletor de arquivos concede ao app permissão para gravar no arquivo.
Pastas restritas
Para ajudar a proteger os usuários e os dados deles, o navegador pode limitar a capacidade do usuário de salvar em determinadas pastas, por exemplo, pastas principais do sistema operacional, como Windows, pastas da Biblioteca macOS etc. Quando isso acontece, o navegador mostra uma solicitação e solicita que o usuário escolha uma pasta diferente.
Como modificar um arquivo ou diretório existente
Um app da Web não pode modificar um arquivo em disco sem receber permissão explícita do usuário.
Solicitação de permissão
Se uma pessoa quiser salvar alterações em um arquivo ao qual tenha concedido acesso de leitura anteriormente, o navegador mostrará um prompt de permissão, solicitando que o site grave alterações no disco. A solicitação de permissão só pode ser acionada por um gesto do usuário, por exemplo, clicando em um botão "Salvar".
![Solicitação de permissão mostrada antes de salvar um arquivo.](https://developer.chrome.com/static/docs/capabilities/web-apis/file-system-access/image/permission-prompt-shown-p-823d180f97ad5.png?authuser=6&hl=pt)
Como alternativa, um app da Web que edita vários arquivos, como um ambiente de desenvolvimento integrado, também pode pedir permissão para salvar mudanças no momento da abertura.
Se o usuário escolher Cancelar e não conceder acesso de gravação, o app da Web não poderá salvar as alterações no arquivo local. Ele precisa fornecer um método alternativo para o usuário salvar os dados, por exemplo, fornecendo uma maneira de "fazer o download" do arquivo, salvando dados na nuvem etc.
Transparência
![Ícone da omnibox](https://developer.chrome.com/static/docs/capabilities/web-apis/file-system-access/image/omnibox-icon-5797e9a831603.jpg?authuser=6&hl=pt)
Quando um usuário concede permissão a um app da Web para salvar um arquivo local, o navegador mostra um ícone na barra de URL. Clicar no ícone abre um pop-over que mostra a lista de arquivos a que o usuário deu acesso. O usuário pode revogar facilmente esse acesso se quiser.
Persistência da permissão
O app da Web pode continuar salvando alterações no arquivo sem solicitar até que todas as guias da origem sejam fechadas. Quando uma guia é fechada, o site perde todo o acesso. Na próxima vez que o usuário usar o app da Web, o acesso aos arquivos vai ser solicitado.
Feedback
Queremos saber sobre a sua experiência com a API File System Access.
Fale sobre o design da API
Algo na API não funciona como você esperava? Ou há métodos ou propriedades ausentes que você precisa para implementar sua ideia? Tem alguma dúvida ou comentário sobre o modelo de segurança?
- Registre um problema de especificação no repositório do GitHub do acesso ao sistema de arquivos WICG no GitHub (em inglês) ou adicione suas ideias a um problema atual.
Problemas com a implementação?
Você encontrou um bug na implementação do Chrome? Ou a implementação é diferente da especificação?
- Registre um bug em https://new.crbug.com. Inclua o máximo de detalhes possível,
instruções simples para reprodução e defina Componentes como
Blink>Storage>FileSystem
. O Glitch funciona muito bem para compartilhar repetições rápidas e fáceis.
Pretende usar a API?
Quer usar a API File System Access no seu site? Seu suporte público nos ajuda a priorizar recursos e mostra a outros fornecedores de navegador como é importante oferecer suporte a eles.
- Conte como você planeja usá-lo na conversa do discurso do WICG (em inglês).
- Envie um tweet para @ChromiumDev usando a hashtag
#FileSystemAccess
e conte onde e como você está usando a hashtag.
Links úteis
- Explicações públicas
- Especificação de acesso ao sistema de arquivos e especificação de arquivos
- Rastreamento de bugs
- Entrada ChromeStatus.com
- Definições do TypeScript
- API File System Access: modelo de segurança do Chromium
- Componente do Blink:
Blink>Storage>FileSystem
Agradecimentos
A especificação da API File System Access foi escrita por Marijn Kruisselbrink.