file_system_access_api library

A Dart library to expose the File System Access API from web platform.

The web API is experimental and is only supported on Chrome, Edge and Opera browsers for now (as of 2022-11).

It provides access to user's local file system to pick files and directories through a dialog.

It returns file entries as a List of FileSystemFileHandle per file selected. A file handle provide a getFile method to read from a File (from 'dart:html' package). It also provide a createWritable method to write in a File, as long as user granted permission.

Permission state and mode.

A file handle provide a queryPermission method to test which permission is granted on file. It's also possible to requestPermission from user to access file handle with PermissionMode.read or PermissionMode.readwrite. Both methods returns a PermissionState upon completion following user's response, which can be: granted, denied or prompt.

Open file picker

TODO: describe showOpenFilePicker()

Example

void main() async {
  try {
    // options: default to one file selection, with all types accepted.
    final handles = await FileSystemAccess.showOpenFilePicker(/*...options*/);
    final handle = handles.single;
    final file = await handle.getFile();
    final reader = FileReader();

    log("${handle.kind} name='${handle.name}' size='${file.size} bytes'");

    reader.readAsText(file);
    await reader.onLoad.first;
    log(reader.result as String);

    // I'm not using queryPermission to keep example short... but it could be used first.
    final state = await handle.requestPermission(mode: PermissionMode.readwrite);

    if (state != PermissionMode.granted) {
      log("User did not grant read / write access on file (either denied access or dismissed prompt).");
      return;
    }
    final stream = await handle.createWritable(keepExistingData: true);

    await stream.write("This message will be appended at the end of the file.");
    await stream.write("File's content will be written on disk only after close() completed.");
    await stream.close();
  } on AbortError {
    log("User dismissed dialog, or picked a file deemed too sensitive or dangerous to be exposed to the website.");
    return;
  }
}

Save file picker

TODO: describe showSaveFilePicker()

Example

void main() async {

}

Directory file picker

TODO: describe showDirectoryFilePicker()

Example

void main() async {
  final directory = await FileSystemAccess.showDirectoryPicker();

  await ls(directory);
}

Future<void> ls(final FileSystemDirectoryHandle directory, [int indent = 0]) async {
  final align = "  " * indent;

  await for (final handle in directory.values) {
    if (handle is FileSystemFileHandle) {
      log("$align${handle.name}");
    } else if (handle is FileSystemDirectoryHandle) {
      log("$align${handle.name}/");
      await ls(handle, indent + 1);
    }
  }
}

See also

Introduction to the web API with examples on web.dev

Documentation on MDN Web Docs

Specification on W3C Community Group Draft Report

Classes

AbortError
Thrown if a user dismisses the prompt without making a selection or if a file selected is deemed too sensitive or dangerous to be exposed to the website.
FilePickerAcceptType
Consists of an optional description and a number of MIME types and extensions (accept). If no description is provided one will be generated. Extensions have to be strings that start with a "." and only contain valid suffix code points. Additionally extensions are limited to a length of 16 characters.
FileSystemAccess
Helpers to bind native JavaScript objects with Dart objects of this library.
FileSystemDirectoryHandle
Provides a handle to a file system directory. The interface is accessed via the FileSystemAccess.showDirectoryPicker method.
FileSystemFileHandle
Represents a handle to a file system entry. The interface is accessed through the FileSystemAccess.showOpenFilePicker method.
FileSystemHandle
Represents a file or directory entry. Multiple handles can represent the same entry. For the most part you do not work with FileSystemHandle directly but rather its child interfaces FileSystemFileHandle and FileSystemDirectoryHandle.
FileSystemSyncAccessHandle
Represents a synchronous handle to a file system entry. The synchronous nature of the file reads and writes allows for higher performance for critical methods in contexts where asynchronous operations come with high overhead, e.g. WebAssembly.
FileSystemWritableFileStream
A WritableStream object with additional convenience methods, which operates on a single file on disk. The interface is accessed through the FileSystemFileHandle.createWritable method.
InvalidModificationError
Thrown if recursive is set to false and the entry to be removed has children.
InvalidStateError
Thrown if the FileSystemSyncAccessHandle object does not represent a file in the origin private file system.
MalformedNameError
Thrown if the name specified is not a valid string or contains characters not allowed on the file system.
NoModificationAllowedError
Thrown if the browser is not able to acquire a lock on the file associated with the file handle.
NotAllowedError
Thrown if you try to access a file while PermissionState is not granted by user.
NotFoundError
Thrown if file doesn't exist and the create option is set to false or the requested file / directory could not be found at the time an operation call was processed.
QuotaExceededError
Thrown if the newSize is larger than the original size of the file, and exceeds the browser's storage quota.
SecurityError
Thrown if a file / directory picker is shown without prior user gesture (e.g. click event).
TypeMismatchError
Thrown if the named entry is a directory and not a file when using FileSystemDirectoryHandle.getFileHandle. Thrown if the named entry is a file and not a directory when using FileSystemDirectoryHandle.getDirectoryHandle.
WritableStream
Provides a standard abstraction for writing streaming data to a destination, known as a sink. This object comes with built-in backpressure and queuing.
WritableStreamDefaultWriter
Is the object returned by WritableStream.getWriter and once created locks the writer to the WritableStream ensuring that no other streams can write to the underlying sink.

Enums

FileSystemKind
It represents a FileSystemHandle.kind. It can be a file or a directory.
PermissionMode
Defines mode to interact with a file using read-only access or read and write access.
PermissionState
A permission represents a user's decision to allow a web application to use a powerful feature. Conceptually, a permission for a powerful feature can be in one of the following states: granted, denied or prompt.
WellKnownDirectory
Lets a website pick one of several well-known directories when used with file picker / directory picker.