katana_storage 2.0.5 katana_storage: ^2.0.5 copied to clipboard
Base package to facilitate switching between Local and Firebase storage implementations.
Katana Storage
[YouTube] | [Packages] | [Twitter] | [LinkedIn]
Introduction #
The ability to upload files representing image files is used by a variety of applications.
Uploading image files, such as social networking and matching applications, can facilitate communication.
There are many cloud services that allow you to upload files and make them available to your application, but if you are using Flutter and Firestore, Cloud Storage for Firebase is probably the best choice for you.
This package implements a package that allows switching between Firebase and local file storage using an adapter similar to the one implemented in katana_model.
Installation #
Import the following packages.
flutter pub add katana_storage
If you use Cloud Storage for Firebase, import the following packages together.
flutter pub add katana_storage_firebase
Implementation #
Advance preparation #
Always place the StorageAdapterScope
widget near the root of the app.
Pass a StorageAdapter such as LocalStorageAdapter
as the parameter adapter.
// main.dart
import 'package:flutter/material.dart';
import 'package:katana_storage/katana_storage.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return StorageAdapterScope(
adapter: const LocalStorageAdapter(),
child: MaterialApp(
home: const StoragePage(),
title: "Flutter Demo",
theme: ThemeData(
primarySwatch: Colors.blue,
),
),
);
}
}
Storage Object Creation #
First, create one Storage
object per file.
Pass a StorageQuery
describing the relative path on the remote side at the time of creation.
Since the Storage object inherits from ChangeNotifier
, it can be used in conjunction with addListener
and riverpod's ChangeNotifierProvider
to monitor its status.
final storage = Storage(const StorageQuery("test/file"));
class StoragePage extends StatefulWidget {
const StoragePage({super.key});
@override
State<StatefulWidget> createState() => StoragePageState();
}
class StoragePageState extends State<StoragePage> {
final storage = Storage(const StorageQuery("test/file"));
final controller = TextEditingController();
@override
void initState() {
super.initState();
storage.addListener(_handledOnUpdate);
}
void _handledOnUpdate() {
setState(() {});
}
@override
void dispose() {
super.dispose();
storage.removeListener(_handledOnUpdate);
storage.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("App Demo")),
body: TextField(
controller: controller,
expands: true,
textAlignVertical: TextAlignVertical.top,
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final text = controller.text;
final bytes = Uint8List.fromList(text.codeUnits);
await storage.uploadWithBytes(bytes);
},
child: const Icon(Icons.upload_file),
),
);
}
}
Uploading #
The following methods are available to perform uploads
upload
:Upload the file by specifying the file path locally.uploadWithBytes
:Upload directly by passing byte data.
A StorageValue
is passed in the return value. The remote full path of the uploaded file is stored here.
final bytes = Uint8List.fromList(text.codeUnits);
final storageValue = await storage.uploadWithBytes(bytes);
print("Remote path is: ${storageValue.remote.path}");
Downloading #
To download a file that has already been uploaded to storage, use the download
method.
It is also possible to specify a relative path to a file to be saved locally as an argument.
StorageValue
is passed as the return value, where the local full path of the downloaded file and the actual data of the file are stored.
Saving to local files is not supported on the Web.
final bytes = Uint8List.fromList(text.codeUnits);
final storageValue = await storage.download("file.jpg");
print("Local path is: ${storageValue.local.path}");
print("Local data is: ${storageValue.local.bytes}");
StorageAdapter #
It is possible to change the storage system by passing StorageAdapterScope
when defining it.
RuntimeStorageAdapter
:Data is uploaded only in the app's memory. It is not actually saved. Please use this function during testing.LocalStorageAdapter
:Storage adapter for storing files locally on the terminal; note that bothlocal
andremote
in download and upload are in the terminal. This is useful for implementing screen mocks.FirebaseStorageAdapter
:Storage adapter to use Cloud Storage for Firebase. Can be used between apps; requires initial Firebase configuration.
Conclusion #
I made it for my own use, but if you think it fits your implementation philosophy, by all means, use it!
Also, I releasing the source here, so issues and PullRequests are welcome!
If you have any further work requests, please contact me directly through my Twitter or website!