filegate 1.6.0
filegate: ^1.6.0 copied to clipboard
A Flutter plugin for native file picking, saving, writing, streamed writing, and streamed file reading across Android, iOS, macOS, Windows, and Linux.
filegate #
A Flutter plugin for native file picking, direct file saving, direct file writing, streamed file writing, and streamed file reading.
The plugin exposes a Dart API for picking files or directory contents, saving bytes through native save/export dialogs, writing bytes to existing files, writing streams to existing files, querying file size, and reading files in chunks without loading the whole file into memory first.
Supported platforms #
- Android
- iOS
- macOS
- Windows
- Linux
All supported platforms provide native picker implementations. Desktop file
reading for paths available to Dart uses dart:io.
Feature comparison #
Compared with this package (filegate 1.6.0) and the latest stable pub.dev
versions checked on 2026-05-18:
file_selector 1.1.0 and
file_picker 11.0.2.
✓ means supported. A blank cell means unsupported or not provided as a
package-level feature.
| Feature | filegate |
file_selector |
file_picker |
|---|---|---|---|
| Android support | ✓ | ✓ | ✓ |
| iOS support | ✓ | ✓ | ✓ |
| macOS support | ✓ | ✓ | ✓ |
| Windows support | ✓ | ✓ | ✓ |
| Linux support | ✓ | ✓ | ✓ |
| Web support | ✓ | ✓ | |
| Single file picking | ✓ | ✓ | ✓ |
| Multiple file picking | ✓ | ✓ | ✓ |
| Extension filtering | ✓ | ✓ | ✓ |
| MIME type filtering | ✓ | ||
| UTI filtering | ✓ | ||
| Directory picking | ✓ | ✓ | ✓ |
| Directory enumeration | ✓ | ||
| Recursive directory enumeration | ✓ | ||
| Mixed file and directory picking | ✓ | ✓ | |
| Save dialog / choose output path | ✓ | ✓ | ✓ |
| One-call save byte payload with dialog | ✓ | ✓ | |
| Save result metadata | ✓ | ||
| Direct write to existing path or URI | ✓ | ||
| Replace existing file without picker | ✓ | ||
| Append to existing file without picker | ✓ | ||
| Empty-byte replace/append contract | ✓ | ||
| Streamed direct write | ✓ | ||
| Streamed write progress callback | ✓ | ||
| Cancellable write session | ✓ | ||
| Chunked file reading | ✓ | ✓ | ✓ |
| Cancellable read session | ✓ | ||
| Read progress helper | ✓ | ||
| Byte range helper | ✓ | ||
| Read all bytes helper | ✓ | ✓ | ✓ |
| Result file size metadata | ✓ | ✓ | ✓ |
| Result modified time metadata | ✓ | ✓ | |
| Result MIME type metadata | ✓ | ✓ | |
| Android persisted URI access option | ✓ |
saveFile is the save/save-as flow for creating or replacing a user-chosen
target. Appending is intentionally modeled as direct writing to an existing
target via writeFile, writeStream, or openWrite with
FilegateWriteMode.append.
Installation #
Add the package to your app:
dependencies:
filegate: ^1.6.0
If you are using this repository directly:
dependencies:
filegate:
path: ../filegate
Then run:
flutter pub get
Platform notes #
Android #
File picking uses the Android Storage Access Framework.
- File selection uses
ACTION_OPEN_DOCUMENT. - Directory selection uses
ACTION_OPEN_DOCUMENT_TREE. - Mixed file and directory selection in one picker call is not supported by the
standard Android SAF intents.
pickMixedreturnsunsupported_modeon Android.
iOS #
File picking uses UIDocumentPickerViewController. Returned document URLs are
read using current-session security-scoped access.
- Directory selection enumerates matching files from the selected directory.
- Mixed file and directory selection returns selected files and files enumerated from selected directories.
macOS #
File picking uses NSOpenPanel. The macOS plugin target requires macOS 11.0 or
newer.
- Directory selection enumerates matching files from the selected directory.
- Mixed file and directory selection returns selected files and files enumerated from selected directories.
Windows #
File picking uses IFileOpenDialog.
- File selection uses the normal open-file dialog.
- Directory selection uses the same dialog in
FOS_PICKFOLDERSmode and then enumerates matching files from the selected directory. - Mixed file and directory selection in one picker call is not supported by the
standard Windows dialog APIs.
pickMixedreturnsunsupported_modeon Windows.
Linux #
File picking uses the GTK file chooser.
- File selection uses
GTK_FILE_CHOOSER_ACTION_OPEN. - Directory selection uses
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDERand then enumerates matching files from the selected directory. - Mixed file and directory selection in one picker call is not supported by the
standard GTK chooser.
pickMixedreturnsunsupported_modeon Linux.
Usage #
Pick files #
import 'package:filegate/filegate.dart';
const filegate = Filegate();
final files = await filegate.pickFiles(
allowMultiple: true,
allowedExtensions: ['txt', '.JSON'],
persistAccess: true,
);
if (files != null) {
for (final file in files) {
print(file.path);
}
}
Pick files from a directory #
final files = await filegate.pickDirectoryFiles(
recursive: true,
allowedExtensions: ['md'],
);
Read a file in chunks #
final session = filegate.openRead('/path/to/file.bin');
await for (final chunk in session.stream) {
print('Read ${chunk.length} bytes');
}
Save bytes to a file #
final saved = await filegate.saveFile(
Uint8List.fromList('hello\n'.codeUnits),
suggestedName: 'hello.txt',
allowedExtensions: ['txt'],
mimeType: 'text/plain',
);
if (saved != null) {
print(saved.path);
}
Append bytes to an existing file #
final updated = await filegate.writeFile(
'/path/to/file.txt',
Uint8List.fromList('more\n'.codeUnits),
mode: FilegateWriteMode.append,
);
print(updated.size);
Stream bytes to an existing file #
final updated = await filegate.writeStream(
'/path/to/file.bin',
Stream<List<int>>.fromIterable([
Uint8List.fromList([1, 2, 3]),
Uint8List.fromList([4, 5, 6]),
]),
);
print(updated.size);
Stream bytes with progress #
final updated = await filegate.writeStream(
'/path/to/file.bin',
Stream<List<int>>.fromIterable([
Uint8List.fromList([1, 2, 3]),
Uint8List.fromList([4, 5, 6]),
]),
totalBytes: 6,
onProgress: (progress) {
print(progress.bytesWritten);
print(progress.progress);
},
);
print(updated.size);
Read with progress #
final session = filegate.openReadWithProgress('/path/to/file.bin');
await for (final chunk in session.stream) {
print(chunk.progress);
}
Read all bytes with a limit #
final bytes = await filegate.readAllBytes(
'/path/to/file.txt',
maxBytes: 1024 * 1024,
);
Read a byte range #
final header = await filegate.readByteRange(
'/path/to/file.bin',
start: 0,
length: 512,
);
List files in a known directory #
final entries = await filegate.listDirectoryFiles(
'/path/to/folder',
recursive: true,
allowedExtensions: ['txt'],
);
API #
The public behavior expected for the 1.0 release track is documented in doc/api_contract.md.
Filegate #
Filegate is the main entry point.
Methods:
getCapabilities(): Returns the current platform capability flags.pick(FilegatePickOptions options): Runs a platform picker.pickFiles(...): Picks one or more files.pickDirectoryFiles(...): Picks a directory and returns matching files.pickMixed(...): Picks files and directories where supported.saveFile(...): Saves an in-memory byte payload through a native save/export dialog.writeFile(...): Replaces or appends bytes to an existing file path or URI.writeStream(...): Replaces or appends streamed byte chunks to an existing file path or URI, with optional cumulative progress callbacks.openWrite(...): Opens a cancellable write session for manual chunk writes, with optional cumulative progress callbacks.getFileSize(String path): Returns a file size when known.openRead(String path, {int chunkSize, int start, int? end}): Opens a cancellable byte stream.startis inclusive andendis exclusive.openReadWithProgress(String path, {int chunkSize, int start, int? end}): Streams chunks with cumulative progress.readAllBytes(String path, {int chunkSize, int? maxBytes}): Reads all bytes with an optional non-negative safety limit.readByteRange(String path, {int start, int length, int chunkSize}): Reads an exact byte range using the streamed reader.listDirectoryFiles(String directoryPath, {bool recursive, List<String> allowedExtensions}): Lists files from a known file-system directory without opening a picker.
Picker results are deduplicated by platform path/URI and returned in deterministic relative path, name, then path order. Directory listing results use the same stable relative path ordering.
FilegatePickOptions #
persistAccess defaults to true for picker helpers. On Android this asks the
Storage Access Framework to persist the selected URI permission when the system
grants one. Set it to false for one-session access.
allowedExtensions values are normalized before dispatch: whitespace is
trimmed, leading dots are removed, case is ignored, and duplicates are dropped.
PickedEntry #
PickedEntry describes a selected file or directory entry. Picker metadata is
best effort and may be omitted when the platform cannot provide it.
Fields:
path: Platform path or URI.name: Display name.kind:PickedEntryKind.fileorPickedEntryKind.directory.relativePath: Path relative to the selected or listed directory when enumerating directory contents.metadata: OptionalPickedEntryMetadatasupplied by native payloads or application code.
Location helpers:
locationKind:platformPath,fileUri,contentUri, orotherUri.isUri: Whetherpathis a URI instead of a platform file path.isContentUri: Whetherpathis an Androidcontent:URI.uri: ParsedUriwhenpathcontains a URI scheme.fileSystemPath: A local file system path for platform paths andfile:URIs, ornullfor identifiers such as Androidcontent:URIs.
Metadata helpers:
size: File size in bytes when known.modifiedAt: Last modified time when known.mimeType: MIME type when known.
FilegateCapabilities #
FilegateCapabilities describes platform differences before showing a picker.
Use it to decide whether to show mixed file/directory selection, initial
directory controls, persistent access messaging, or URI-read flows.
Fields:
supportsFilePickingsupportsDirectoryPickingsupportsMixedPickingsupportsInitialDirectorysupportsPersistedAccesssupportsNativeUriReadsupportsFileSavingsupportsFileWritingsupportsFileStreamWriting
Errors #
Native failures are surfaced as PlatformExceptions. Common error codes are
available in FilegateErrorCode, including invalid_args,
unsupported_mode, no_activity, no_view_controller, picker_active,
path_not_found, not_a_file, not_a_directory, permission_denied,
persist_permission_failed, security_scope_failed, pick_failed,
picker_failed, save_failed, write_failed, stream_active,
missing_stream_id, missing_write_session_id, write_session_not_found,
invalid_chunk, read_open_failed, read_failed, and enumeration_failed.