top of page

[Flutter/dart] Manage your data with a combination of Cloud Firestore and Firebase_Storage


Overview


If you want to save user information etc. in a serverless application, you probably use cloud fire store. However, only values such as int and string can be saved in firestore, and you need to use firebase_storage to save images.

This time, I will introduce how to manage user data (images & data such as int, String, etc.) by combining these two.



Method


Overview: upploading

  1. User uploads local image → Get local image path

  2. Save the image in storage with a suitable name

  3. Save local image path and storage image path to firestore



Overview: downloading

  1. Get the local image path and path of storage destination from the firestore

  2. If the image remains in local directory, use that image path

  3. Download from storage if the image does not left in local directory




Upload image


I think that you often use ImagePicker to upload images.

static Future<String> select_icon(BuildContext context) async{

  static const String SELECT_ICON = "select icon";
  static const List<String> SELECT_ICON_OPTIONS = 
    ["select from gallery", "take picture"];
  static const int GALLERY = 0;
  static const int CAMERA = 1;
  
  var _select_type=await showDialog(
      context: context,
      builder: (BuildContext context){
        return SimpleDialog(
          title: Text(SELECT_ICON),
          children: SELECT_ICON_OPTIONS.asMap().entries.map((e) {
            return SimpleDialogOption(
              child: ListTile(
                title: Text(e.value),
              ),
              onPressed: ()=>Navigator.of(context).pop(e.key),
            );
          }).toList(),
        ) ;
      });

  final picker=ImagePicker();
  var  _img_src;

  if (_select_type==null){
    return null;
  }
  //take picture by camera
  else if (_select_type==CAMERA){
    _img_src=ImageSource.camera;
  }
  //select from gallery
  else if (_select_type==GALLERY){
    _img_src=ImageSource.gallery;
  }

  final pickedFile = await picker.getImage(source: _img_src);

  if (pickedFile==null){
    return null;
  }
  else{
    return pickedFile.path;
  }
}

When you get an image with ImagePicker, the image is saved in the local folder, so get the path and save it as the local path.



Save image in Firebase Storage


Create the following method according to the official site.

import 'dart:io' as io;

Future<void> uploadFile(String sourcePath, String uploadFileName) async{

    final FirebaseStorage storage=FirebaseStorage.instance;
    Reference ref=storage.ref().child("images");  //save folder
    
    io.File file=io.File(sourcePath);
    UploadTask task=ref.child(uploadFileName).putFile(file);
    
    try{
      var snapshot=await task;
    }
    catch(FirebaseException){
      //error handling
    }
  }

Enter the local path obtained earlier in sourcePath and a unique name in uploadFileName.

You have now uploaded your image to Firebase Storage.



Save image file path


Finally, save the above local image path and the path saved in storage to firestore (in String type).


For example, if there is a collection for each user, the method to add the image path to each user's data is as follows. (Official) (The document id is given as the first argument)

Future<void> addFilePath(String userId, String localPath, 
  String remotePath){
    
  CollectionReference users = 
    FirebaseFirestore.instance.collection('users');
    
  await users.doc(userId)
  .set(
   {
     'localPath': localPath,
     'remotePath': remotePath,
   }, 
   SetOptions(merge: true)
  );
}


Download image


From the firestore, get the local path and the save destination path to the storage of the previously saved image as a String type.

If you have images left locally, you don't have to download them from storage, so check this first.

If the image remains locally, pass the path to Image etc.

If it doesn't remain locally, download the image from storage and pass the path to Image etc.


The following method returns the local path or the storage path, whichever is appropriate.

Future<String> _getImgs(String imgPathLocal, String imgPathRemote) async{

    bool existLocal=await io.File(imgPathLocal).exists();
    String imgPathUse="";

    if (existLocal) {
      //Use local image if it exists locally
      imgPathUse=imgPathLocal;
    }
    else {
      if ((imgPathRemote != "") && (imgPathRemote != null)) {
        try {
          //Download remote data if it does not exist locally
          imgPathUse = await FirebaseStorage.instance.ref().
            child("images").child(imgPathRemote).getDownloadURL();
        }
        catch (FirebaseException) {
          imgPathUse = "";
        }
      }
      else{
        imgPathUse="";
      }
    }    
  return imgPathUse;
}


Lastly


If you want to make something like SNS, you will prepare a server, but even with a serverless application, you may want to let the user set a small image such as an icon image. In such a case, please refer to it.

However, since it is operated only by personal development, please use it as a reference.

Recent Posts

See All

[Flutter/Dart] Format string with TextField

What want to do I want to create an input form using TextField. For example, if the input content is a monetary amount, I would like to display it in 3-digit delimiters with a ¥ prefix. Rather than ha

Comments


Let's do our best with our partner:​ ChatReminder

iphone6.5p2.png

It is an application that achieves goals in a chat format with partners.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

Let's do our best with our partner:​ ChatReminder

納品:iPhone6.5①.png

It is an application that achieves goals in a chat format with partners.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

Theme diary: Decide the theme and record for each genre

It is a diary application that allows you to post and record with themes and sub-themes for each genre.

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png
bottom of page