firebase_storage 10.0.1
firebase_storage: ^10.0.1 copied to clipboard
Flutter plugin for Firebase Cloud Storage, a powerful, simple, and cost-effective object storage service for Android and iOS.
example/lib/main.dart
// @dart=2.9
import 'dart:async';
import 'dart:io' as io;
import 'package:firebase_core/firebase_core.dart' as firebase_core;
import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'save_as/save_as.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await firebase_core.Firebase.initializeApp();
runApp(StorageExampleApp());
}
/// Enum representing the upload task types the example app supports.
enum UploadType {
/// Uploads a randomly generated string (as a file) to Storage.
string,
/// Uploads a file from the device.
file,
/// Clears any tasks from the list.
clear,
}
/// The entry point of the application.
///
/// Returns a [MaterialApp].
class StorageExampleApp extends StatelessWidget {
StorageExampleApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Storage Example App',
theme: ThemeData.dark(),
home: Scaffold(
body: TaskManager(),
));
}
}
/// A StatefulWidget which keeps track of the current uploaded files.
class TaskManager extends StatefulWidget {
// ignore: public_member_api_docs
TaskManager({Key key}) : super(key: key);
@override
State<StatefulWidget> createState() {
return _TaskManager();
}
}
class _TaskManager extends State<TaskManager> {
List<firebase_storage.UploadTask> _uploadTasks = [];
/// The user selects a file, and the task is added to the list.
Future<firebase_storage.UploadTask> uploadFile(PickedFile file) async {
if (file == null) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('No file was selected'),
));
return null;
}
firebase_storage.UploadTask uploadTask;
// Create a Reference to the file
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.ref()
.child('playground')
.child('/some-image.jpg');
final metadata = firebase_storage.SettableMetadata(
contentType: 'image/jpeg',
customMetadata: {'picked-file-path': file.path});
if (kIsWeb) {
uploadTask = ref.putData(await file.readAsBytes(), metadata);
} else {
uploadTask = ref.putFile(io.File(file.path), metadata);
}
return Future.value(uploadTask);
}
/// A new string is uploaded to storage.
firebase_storage.UploadTask uploadString() {
const String putStringText =
'This upload has been generated using the putString method! Check the metadata too!';
// Create a Reference to the file
firebase_storage.Reference ref = firebase_storage.FirebaseStorage.instance
.ref()
.child('playground')
.child('/put-string-example.txt');
// Start upload of putString
return ref.putString(putStringText,
metadata: firebase_storage.SettableMetadata(
contentLanguage: 'en',
customMetadata: <String, String>{'example': 'putString'}));
}
/// Handles the user pressing the PopupMenuItem item.
Future<void> handleUploadType(UploadType type) async {
switch (type) {
case UploadType.string:
setState(() {
_uploadTasks = [..._uploadTasks, uploadString()];
});
break;
case UploadType.file:
PickedFile file =
await ImagePicker().getImage(source: ImageSource.gallery);
firebase_storage.UploadTask task = await uploadFile(file);
if (task != null) {
setState(() {
_uploadTasks = [..._uploadTasks, task];
});
}
break;
case UploadType.clear:
setState(() {
_uploadTasks = [];
});
break;
}
}
void _removeTaskAtIndex(int index) {
setState(() {
_uploadTasks = _uploadTasks..removeAt(index);
});
}
Future<void> _downloadBytes(firebase_storage.Reference ref) async {
final bytes = await ref.getData();
// Download...
await saveAsBytes(bytes, 'some-image.jpg');
}
Future<void> _downloadLink(firebase_storage.Reference ref) async {
final link = await ref.getDownloadURL();
await Clipboard.setData(ClipboardData(
text: link,
));
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(
'Success!\n Copied download URL to Clipboard!',
),
),
);
}
Future<void> _downloadFile(firebase_storage.Reference ref) async {
final io.Directory systemTempDir = io.Directory.systemTemp;
final io.File tempFile = io.File('${systemTempDir.path}/temp-${ref.name}');
if (tempFile.existsSync()) await tempFile.delete();
await ref.writeToFile(tempFile);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Success!\n Downloaded ${ref.name} \n from bucket: ${ref.bucket}\n '
'at path: ${ref.fullPath} \n'
'Wrote "${ref.fullPath}" to tmp-${ref.name}.txt',
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Storage Example App'),
actions: [
PopupMenuButton<UploadType>(
onSelected: handleUploadType,
icon: const Icon(Icons.add),
itemBuilder: (context) => [
const PopupMenuItem(
// ignore: sort_child_properties_last
child: Text('Upload string'),
value: UploadType.string),
const PopupMenuItem(
// ignore: sort_child_properties_last
child: Text('Upload local file'),
value: UploadType.file),
if (_uploadTasks.isNotEmpty)
const PopupMenuItem(
// ignore: sort_child_properties_last
child: Text('Clear list'),
value: UploadType.clear)
],
)
],
),
body: _uploadTasks.isEmpty
? const Center(child: Text("Press the '+' button to add a new file."))
: ListView.builder(
itemCount: _uploadTasks.length,
itemBuilder: (context, index) => UploadTaskListTile(
task: _uploadTasks[index],
onDismissed: () => _removeTaskAtIndex(index),
onDownloadLink: () {
return _downloadLink(_uploadTasks[index].snapshot.ref);
},
onDownload: () {
if (kIsWeb) {
return _downloadBytes(_uploadTasks[index].snapshot.ref);
} else {
return _downloadFile(_uploadTasks[index].snapshot.ref);
}
},
),
),
);
}
}
/// Displays the current state of a single UploadTask.
class UploadTaskListTile extends StatelessWidget {
// ignore: public_member_api_docs
const UploadTaskListTile({
Key key,
this.task,
this.onDismissed,
this.onDownload,
this.onDownloadLink,
}) : super(key: key);
/// The [UploadTask].
final firebase_storage.UploadTask /*!*/ task;
/// Triggered when the user dismisses the task from the list.
final VoidCallback /*!*/ onDismissed;
/// Triggered when the user presses the download button on a completed upload task.
final VoidCallback /*!*/ onDownload;
/// Triggered when the user presses the "link" button on a completed upload task.
final VoidCallback /*!*/ onDownloadLink;
/// Displays the current transferred bytes of the task.
String _bytesTransferred(firebase_storage.TaskSnapshot snapshot) {
return '${snapshot.bytesTransferred}/${snapshot.totalBytes}';
}
@override
Widget build(BuildContext context) {
return StreamBuilder<firebase_storage.TaskSnapshot>(
stream: task.snapshotEvents,
builder: (
BuildContext context,
AsyncSnapshot<firebase_storage.TaskSnapshot> asyncSnapshot,
) {
Widget subtitle = const Text('---');
firebase_storage.TaskSnapshot snapshot = asyncSnapshot.data;
firebase_storage.TaskState state = snapshot?.state;
if (asyncSnapshot.hasError) {
if (asyncSnapshot.error is firebase_core.FirebaseException &&
(asyncSnapshot.error as firebase_core.FirebaseException).code ==
'canceled') {
subtitle = const Text('Upload canceled.');
} else {
// ignore: avoid_print
print(asyncSnapshot.error);
subtitle = const Text('Something went wrong.');
}
} else if (snapshot != null) {
subtitle = Text('$state: ${_bytesTransferred(snapshot)} bytes sent');
}
return Dismissible(
key: Key(task.hashCode.toString()),
onDismissed: ($) => onDismissed(),
child: ListTile(
title: Text('Upload Task #${task.hashCode}'),
subtitle: subtitle,
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
if (state == firebase_storage.TaskState.running)
IconButton(
icon: const Icon(Icons.pause),
onPressed: task.pause,
),
if (state == firebase_storage.TaskState.running)
IconButton(
icon: const Icon(Icons.cancel),
onPressed: task.cancel,
),
if (state == firebase_storage.TaskState.paused)
IconButton(
icon: const Icon(Icons.file_upload),
onPressed: task.resume,
),
if (state == firebase_storage.TaskState.success)
IconButton(
icon: const Icon(Icons.file_download),
onPressed: onDownload,
),
if (state == firebase_storage.TaskState.success)
IconButton(
icon: const Icon(Icons.link),
onPressed: onDownloadLink,
),
],
),
),
);
},
);
}
}