Flutter Firebase Image & File Upload CRUD

Flutter Firebase Image & File Upload CRUD

    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(),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }

    Courses


    Recommended posts


    Recent posts