Complete BLoC with Clean Architecture (group chat) Discount !! E-commerce App With Backend Source Code Video and Voice Chatting App Firebase Chatting App Source Code Complete Gym App BLoC State Management Source Code Complete Study App Buy Ticket Booking App Source Code Buy Travel App With Backend Source Code Complete Chat App Udemy Course Special Offer Discount !! Online Learning Course App (BLoC) Online Learning Course App (Riverpod) Online Learning Course App (Getx) Discount !! Shopping App (Provider) Cool Flutter Game Nodejs Flutter Complete App
Previously we did Flutter Firebase CRUD for text information. Flutter firebase image and file upload we will use three plugins.
firebase_storage:
image_picker:
path:
First create a project and then install the above three plugins.
Android settings
Android doesn't need much settings. Just in AndroidManifest.xml file do the follow
android:requestLegacyExternalStorage=”true”
iOS settings
iOS setting is also relatively easy. Just put the code in the Info.plist right after first <dict>
<key>NSCameraUsageDescription</key>
<string>Some Description</string>
<key>NSMicrophoneUsageDescription</key>
<string>Some Description</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Some Description</string>
Warnings: iOS simulator on Mac M1 chip doesn't support a stable image_picker plugin.
Core functions
≥ await picker.pickImage()
≥ await storage.ref(fileName).putFile()
Complete code
// main.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart' as path;
import 'package:image_picker/image_picker.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Initialize a new Firebase App instance
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'dbestech',
theme: ThemeData(primarySwatch: Colors.green),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
FirebaseStorage storage = FirebaseStorage.instance;
// Select and image from the gallery or take a picture with the camera
// Then upload to Firebase Storage
Future<void> _upload(String inputSource) async {
final picker = ImagePicker();
XFile? pickedImage;
try {
pickedImage = await picker.pickImage(
source: inputSource == 'camera'
? ImageSource.camera
: ImageSource.gallery,
maxWidth: 1920);
final String fileName = path.basename(pickedImage!.path);
File imageFile = File(pickedImage.path);
try {
// Uploading the selected image with some custom meta data
await storage.ref(fileName).putFile(
imageFile,
SettableMetadata(customMetadata: {
'uploaded_by': 'learners',
'description': 'learning the hacks'
}));
// Refresh the UI
setState(() {});
} on FirebaseException catch (error) {
if (kDebugMode) {
print(error);
}
}
} catch (err) {
if (kDebugMode) {
print(err);
}
}
}
// Retriew the uploaded images
// This function is called when the app launches for the first time or when an image is uploaded or deleted
Future<List<Map<String, dynamic>>> _loadImages() async {
List<Map<String, dynamic>> files = [];
final ListResult result = await storage.ref().list();
final List<Reference> allFiles = result.items;
await Future.forEach<Reference>(allFiles, (file) async {
final String fileUrl = await file.getDownloadURL();
final FullMetadata fileMeta = await file.getMetadata();
files.add({
"url": fileUrl,
"path": file.fullPath,
"uploaded_by": fileMeta.customMetadata?['uploaded_by'] ?? 'Nobody',
"description":
fileMeta.customMetadata?['description'] ?? 'No description'
});
});
return files;
}
// Delete the selected image
// This function is called when a trash icon is pressed
Future<void> _delete(String ref) async {
await storage.ref(ref).delete();
// Rebuild the UI
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('dbestech),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton.icon(
onPressed: () => _upload('camera'),
icon: const Icon(Icons.camera),
label: const Text('camera')),
ElevatedButton.icon(
onPressed: () => _upload('gallery'),
icon: const Icon(Icons.library_add),
label: const Text('Gallery')),
],
),
Expanded(
child: FutureBuilder(
future: _loadImages(),
builder: (context,
AsyncSnapshot<List<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return ListView.builder(
itemCount: snapshot.data?.length ?? 0,
itemBuilder: (context, index) {
final Map<String, dynamic> image =
snapshot.data![index];
return Card(
margin: const EdgeInsets.symmetric(vertical: 10),
child: ListTile(
dense: false,
leading: Image.network(image['url']),
title: Text(image['uploaded_by']),
subtitle: Text(image['description']),
trailing: IconButton(
onPressed: () => _delete(image['path']),
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
),
);
},
);
}
return const Center(
child: CircularProgressIndicator(),
);
},
),
),
],
),
),
);
}
}