Search the site
DATA
Store files with one API on the device's own disk, a server's disk, S3, Google Cloud Storage or Azure Blob Storage.
Swap the adapter and your code stays the same.
ON THIS PAGE
Configure a storage adapter
Put, get, list and delete files
Files on the device: DV.Platform.fileStorage
Status
The same calls wherever the files are. On a server that can be the server's own disk; on a device it is the directory the application owns, which is what a file manager writes into. A bucket is one more adapter behind them.
// The filesystem this process is standing on. On a server that is the
// server's disk; on a device it is the directory the application owns, which
// is what a file manager writes into. Same calls either way.
void storeOnDisk(String directory) {
DV.FileStorage.configure(DVLocalFileStorageAdapter(root: directory));
}Copy code to clipboard
// A bucket is one more adapter behind the same calls. Swapping this line is
// the whole of moving from a disk to S3.
void configureStorage() {
DV.FileStorage.configure(S3FileStorageAdapter(
bucket: 'uploads',
region: 'eu-west-1',
credentials: DVAwsCredentials(
accessKeyId: DV.Secrets.get('AWS_ACCESS_KEY_ID'),
secretAccessKey: DV.Secrets.get('AWS_SECRET_ACCESS_KEY'),
),
));
}Copy code to clipboard
DVLocalFileStorageAdapter
Stores files in: The filesystem: a server's disk, or the directory an app owns on a device
DVMemoryFileStorageAdapter
Stores files in: Memory, the default
S3FileStorageAdapter
Stores files in: Amazon S3, or any S3 API with endpoint:
GcsFileStorageAdapter
Stores files in: Google Cloud Storage
AzureBlobFileStorageAdapter
Stores files in: Azure Blob Storage
A key is a path inside the root, and often comes from a request. One that climbs out of the root is refused, so a ../ in a key cannot read or overwrite anything else the process can reach.
A browser has no such filesystem, so DVLocalFileStorageAdapter there answers every call with a 501. On a device in a browser, use DV.Platform.fileStorage below, which is the origin private file system.
await DV.FileStorage.put('avatars/ada.png', bytes, contentType: 'image/png');
if (await DV.FileStorage.exists('avatars/ada.png')) {
final List<int> image = await DV.FileStorage.get('avatars/ada.png');
DV.log('${image.length} bytes');
}
final List<String> avatars = await DV.FileStorage.list(prefix: 'avatars/');
await DV.FileStorage.delete('avatars/ada.png');Copy code to clipboard
Keys are paths you choose, such as avatars/ada.png.
There is no public URL or signed URL method. Serve files through a backend function.
Use DV.FileStorage
DV.Storage is the old name. It still works and is deprecated, so new code should not use it.
DV.Platform.fileStorage is DV.FileStorage on the device's own disk: the same calls, bound to the local adapter whatever DV.FileStorage is configured with. Keys go in the directory each platform gives an app for its own files, which needs no permission anywhere.
// The device's own disk, whatever adapter DV.FileStorage is configured with.
// App-private: no permission on any platform.
await DV.Platform.fileStorage.put('drafts/note.txt', bytes);
final List<String> drafts = await DV.Platform.fileStorage.list(prefix: 'drafts/');
await DV.Platform.fileStorage.cache.put('thumbs/note.png', bytes);
// A file the person picks. Choosing it is the grant, so nothing is declared.
final List<DVPickedFile> picked = await DV.Platform.fileStorage.pick(type: 'image');
for (final DVPickedFile file in picked) {
await DV.Platform.fileStorage.put('attachments/${file.name}', await file.readBytes());
}
// A folder the person picks, as a storage with the same calls.
final DVStorage? folder = await DV.Platform.fileStorage.pickDirectory();
await folder?.put('export.csv', bytes);
// Wider access, declared under dartvel.fileStorage in pubspec.yaml.
try {
await DV.Platform.fileStorage.requestAccess(.photos);
} on DVFileAccessDenied catch (refused) {
DV.log(refused.reason);
}Copy code to clipboard
Android
App files: dartvel-files in the app's files directory; cache in its cache directory
Files the person picks: The system picker, a private copy by path. No folders yet.
iOS
App files: Documents in the app container (in the Files app with shareAppFiles)
Files the person picks: Not bound yet
macOS
App files: ~/Library/Application Support/<app>
Files the person picks: Open panel and folder panel
Windows
App files: %LOCALAPPDATA%\<app>\Files
Files the person picks: Open dialog and folder dialog
Linux and embedded Linux
App files: $XDG_DATA_HOME/<app> (~/.local/share/<app>)
Files the person picks: GTK file and folder chooser
Web
App files: The origin private file system
Files the person picks: A file input in every browser. Folders: showDirectoryPicker in Chromium (read and write); a folder input elsewhere (read only)
Declare it once under dartvel.fileStorage in pubspec.yaml, or in your DartvelConfig class. The build writes it the way each platform expects, and requestAccess asks for it at run time.
# What DV.Platform.fileStorage may reach beyond the app's own directory.
# Leave it out and the app reads and writes only its own files.
fileStorage:
access: [photos, documents] # also: media, allFiles
reason: Attach photos and receipts to your orders.
shareAppFiles: true # iOS: show the app's Documents in FilesCopy code to clipboard
photos
Android (written to the manifest): READ_MEDIA_IMAGES (13+), READ_MEDIA_VISUAL_USER_SELECTED (14+), READ_EXTERNAL_STORAGE (12 and below)
iOS and macOS: NSPhotoLibraryUsageDescription with your reason; macOS: pictures read-only entitlement
media
Android (written to the manifest): Photos plus READ_MEDIA_VIDEO and READ_MEDIA_AUDIO
iOS and macOS: As photos; macOS also movies and music entitlements
documents
Android (written to the manifest): Nothing: the picker is the grant
iOS and macOS: macOS: user-selected read-write entitlement
allFiles
Android (written to the manifest): MANAGE_EXTERNAL_STORAGE (11+): a Settings switch, and Google Play allows it only for apps that need it
iOS and macOS: iOS has none; macOS sandbox has none (the build says so)
shareAppFiles: true adds UIFileSharingEnabled and LSSupportsOpeningDocumentsInPlace on iOS.
Windows, Linux and the web need nothing at build time: a desktop process reads what its user can, and a browser asks when the person picks.
Keys you already set in Info.plist or the entitlements are yours: the build keeps them and does not write a second copy.
requestAccess throws DVFileAccessDenied when the person refuses, and a StateError naming the pubspec key when the access was never declared.
DV.Platform.files is deprecated
Use DV.Platform.fileStorage: put, get and delete in the same directory on Android and the web, and every other target too.
Partial
Spec section: File Storage
Planned work and implementation limits
No putStream or getStream, so a file is read and written whole.
FSL-1.1-MIT licensed. Built with Dartvel.
Dartvel is made by
To the bottom