Dart and Flutter
There is no official AWS SDK for Dart, but the minio Dart package is a mature S3 client that works against any S3-compatible service.
Install
pubspec.yaml
dependencies:
minio: ^3.5.0
Initialize the client
lib/filebase.dart
import 'package:minio/minio.dart';
final filebase = Minio(
endPoint: 's3.filebase.io',
accessKey: const String.fromEnvironment('FILEBASE_KEY'),
secretKey: const String.fromEnvironment('FILEBASE_SECRET'),
region: 'auto',
useSSL: true,
);
List buckets
final buckets = await filebase.listBuckets();
for (final b in buckets) {
print(b.name);
}
Create a bucket
await filebase.makeBucket('my-bucket');
Upload an object
import 'dart:io';
final file = File('photo.jpg');
final stream = file.openRead().cast<List<int>>();
final length = await file.length();
await filebase.putObject(
'my-bucket',
'photo.jpg',
stream,
size: length,
metadata: {'Content-Type': 'image/jpeg'},
);
For Flutter mobile uploads, the image_picker plugin gives you an XFile:
import 'package:image_picker/image_picker.dart';
final picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
final bytes = await image.readAsBytes();
await filebase.putObject(
'uploads',
'user-${userId}/${image.name}',
Stream.value(bytes),
size: bytes.length,
);
}
List objects
final stream = filebase.listObjects('my-bucket', prefix: 'photos/');
await for (final result in stream) {
for (final obj in result.objects) {
print('${obj.key} ${obj.size}');
}
}
Download an object
import 'dart:io';
final stream = await filebase.getObject('my-bucket', 'photo.jpg');
final file = File('./downloaded.jpg');
final sink = file.openWrite();
await stream.pipe(sink);
Delete an object
await filebase.removeObject('my-bucket', 'photo.jpg');
Pre-signed URLs
final url = await filebase.presignedGetObject(
'my-bucket',
'private.pdf',
expires: 3600,
);
print(url);
Error handling
try {
await filebase.statObject('my-bucket', 'maybe.jpg');
} on MinioError catch (e) {
if (e.code == 'NoSuchKey') {
// handle missing
} else {
rethrow;
}
}
What's next
- Pre-signed URLs
- Browser uploads recipe — same pattern works for mobile