Upload Files

Upload files directly from the device to Cloudflare R2. The SDK handles the presigned URL, upload, and confirmation in one call.

Basic upload

Pass a File object, a bucket name, and a path within that bucket. The SDK handles the presigned URL exchange and upload automatically.

lib/storage.dartDart
import 'dart:io';

final file = File('/path/to/image.jpg');

final result = await Koolbase.storage.upload(
  file,
  bucket: 'avatars',
  path: 'user_${userId}.jpg',
);

print(result.path);        // user_abc123.jpg
print(result.bucket);      // avatars
print(result.size);        // file size in bytes
print(result.contentType); // image/jpeg

Upload from bytes

If you have file bytes rather than a file path — for example from an image picker — use uploadBytes():

lib/storage.dartDart
import 'package:image_picker/image_picker.dart';

final picker = ImagePicker();
final picked = await picker.pickImage(source: ImageSource.gallery);

if (picked != null) {
  final bytes = await picked.readAsBytes();

  final result = await Koolbase.storage.uploadBytes(
    bytes,
    bucket: 'avatars',
    path: 'user_${userId}.jpg',
    contentType: 'image/jpeg',
  );

  print(result.path); // user_abc123.jpg
}

Upload with progress

Track upload progress for large files using the onProgress callback:

lib/storage.dartDart
await Koolbase.storage.upload(
  file,
  bucket: 'documents',
  path: 'reports/${filename}',
  onProgress: (sent, total) {
    final percent = (sent / total * 100).toStringAsFixed(1);
    setState(() => uploadProgress = sent / total);
    print('Upload: $percent%');
  },
);

Content type detection

Koolbase automatically detects the content type from the file extension. You can override it explicitly using the contentType parameter:

lib/storage.dartDart
// Auto-detected from .pdf extension
await Koolbase.storage.upload(
  file,
  bucket: 'documents',
  path: 'report.pdf',
);

// Explicitly set content type
await Koolbase.storage.upload(
  file,
  bucket: 'exports',
  path: 'data.json',
  contentType: 'application/json',
);

Supported file types

Koolbase Storage accepts any file type. The content type is stored as metadata and used when serving the file from R2. Always set the correct content type for files that will be opened directly in a browser.

Error handling

lib/storage.dartDart
try {
  await Koolbase.storage.upload(
    file,
    bucket: 'avatars',
    path: 'user_${userId}.jpg',
  );
} on KoolbaseStorageException catch (e) {
  switch (e.code) {
    case 'bucket_not_found':
      showError('Storage bucket does not exist');
    case 'file_too_large':
      showError('File exceeds maximum allowed size');
    case 'upload_failed':
      showError('Upload failed — please try again');
    default:
      showError('Upload error: ${e.message}');
  }
}

Path conflicts

Uploading to a path that already exists will overwrite the existing file. There is no versioning — if you need to keep previous files, use unique paths (e.g. include a timestamp or UUID in the filename).