How to upload image to Firebase using Flutter

14,225

Solution 1

Updated version of mmccabe's answer that works with version 1.0.4 of the firebase_storage plugin

Future<String> _pickSaveImage(String imageId) async {
  File imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  StorageReference ref =
    FirebaseStorage.instance.ref().child(imageId).child("image.jpg");
  StorageUploadTask uploadTask = ref.putFile(imageFile);
  return await (await uploadTask.onComplete).ref.getDownloadURL();
}

As of now you have to do:

var downloadURL = (await uploadTask.onComplete).ref.getDownloadURL();

because error: The getter 'future' isn't defined for the class 'StorageUploadTask'. (undefined_getter at [timetracker] lib/screens/image_detection.dart:63)

Solution 2

The following works for me:

Future<Uri> _pickSaveImage(String imageId) async {
  File imageFile = await ImagePicker.pickImage(source: ImageSource.camera);
  StorageReference ref =
    FirebaseStorage.instance.ref().child(imageId).child("image.jpg");
  StorageUploadTask uploadTask = ref.putFile(imageFile);
  return (await uploadTask.future).downloadUrl;
}

Solution 3

This worked for me... In my case, I also needed to get the download URL and push to a firestore collection. After doing some reading I found that it's best to use a StorageTaskSnapshot and then get download URL

uploadImage(File image) async {
    StorageReference reference =
             FirebaseStorage.instance.ref().child(image.path.toString());
    StorageUploadTask uploadTask = reference.putFile(image);

    StorageTaskSnapshot downloadUrl = (await uploadTask.onComplete);

    String url = (await downloadUrl.ref.getDownloadURL());


}
Share:
14,225
Marko
Author by

Marko

Updated on June 07, 2022

Comments

  • Marko
    Marko about 2 years

    I am using the image_picker library https://pub.dartlang.org/packages/image_picker with for selecting/taking the photo that I want to upload. The code so far uploads the image to Firebase storage successfully the only issue is that after the image is uploaded the app shuts down (doesn't really crash, it just closes and VS code looses connection to the device). The code is the following:

     File _image;
    
      Future _takeProfilePicture() async{
        var image = await ImagePicker.pickImage(source: ImageSource.camera);
    
        setState((){
          _image = image;
        });
      }
    
      Future _selectProfilePicture() async{
        var image = await ImagePicker.pickImage(source: ImageSource.gallery);
    
        setState((){
          _image = image;
        });
      }
    
      Future<Null> _uploadProfilePicture() async{
        FirebaseUser user = await FirebaseAuth.instance.currentUser();
    
        final StorageReference ref = FirebaseStorage.instance.ref().child('${user.email}/${user.email}_profilePicture.jpg');
        final StorageUploadTask uploadTask = ref.putFile(_image);
        final Uri downloadUrl = (await uploadTask.future).downloadUrl;
      }
    
      void _selectAndUploadPicture() async{
        await _selectProfilePicture();
        await _uploadProfilePicture();
      }
    
      void _takeAndUploadPicture() async{
        await _takeProfilePicture();
        await _uploadProfilePicture();
      }
    

    And the terminal prints the following:

    W/Firestore( 6873): (0.6.6-dev) [Firestore]: The behavior for java.util.Date objects stored in Firestore is going to change AND YOUR APP MAY BREAK.
    W/Firestore( 6873): To hide this warning and ensure your app does not break, you need to add the following code to your app before calling any other Cloud Firestore methods:
    W/Firestore( 6873):
    W/Firestore( 6873): FirebaseFirestore firestore = FirebaseFirestore.getInstance();
    W/Firestore( 6873): FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
    W/Firestore( 6873):     .setTimestampsInSnapshotsEnabled(true)
    W/Firestore( 6873):     .build();
    W/Firestore( 6873): firestore.setFirestoreSettings(settings);
    W/Firestore( 6873):
    W/Firestore( 6873): With this change, timestamps stored in Cloud Firestore will be read back as com.google.firebase.Timestamp objects instead of as system java.util.Date objects. So you will also need to update code expecting a java.util.Date to instead expect a Timestamp. For example:
    W/Firestore( 6873):
    W/Firestore( 6873): // Old:
    W/Firestore( 6873): java.util.Date date = snapshot.getDate("created_at");
    W/Firestore( 6873): // New:
    W/Firestore( 6873): Timestamp timestamp = snapshot.getTimestamp("created_at");
    W/Firestore( 6873): java.util.Date date = timestamp.toDate();
    W/Firestore( 6873):
    W/Firestore( 6873): Please audit all existing usages of java.util.Date when you enable the new behavior. In a future release, the behavior will be changed to the new behavior, so if you do not follow these steps, YOUR APP MAY BREAK.
    

    I tried implementing the suggested java code from the terminal but I cannot seem to find a way to write the equivalent in flutter using the cloud_firestore library https://pub.dartlang.org/packages/cloud_firestore , it does not have an equivalent for FirebaseFirestoreSettings (or I cannot seem to find one). Is there a way around this?

    Thank you in advance!

  • Marko
    Marko almost 6 years
    Seem to have the same issue :(
  • mmccabe
    mmccabe almost 6 years
    Once the image is stored, you can display it using Image.network(uriOfImage).image.
  • Yarm
    Yarm over 5 years
    This works. But if a second image is uploaded in quick succession, then the app will crash.
  • SacWebDeveloper
    SacWebDeveloper almost 5 years
    Why does it fail? How to fix?
  • Sludge
    Sludge almost 4 years
    FYI: 'ImagePicker.pickImage' is deprecated and shouldn't be used. Use ImagePicker.getImage() method instead -- This also means you have to change the type File to PickedFile (e.g., PickedFile imageFile = await ImagePicker.getImage(...))