Flutter Upload batch of images and get all those URLs to store in Firestore

7,622

Solution 1

You could use this method for multiple file upload to firebase storage where List<Asset> assets are your List<File> files.

Future<List<String>> uploadImage(
      {@required String fileName, @required List<Asset> assets}) async {
    List<String> uploadUrls = [];

    await Future.wait(assets.map((Asset asset) async {
      ByteData byteData = await asset.requestOriginal();
      List<int> imageData = byteData.buffer.asUint8List();

      StorageReference reference = FirebaseStorage.instance.ref().child(fileName);
      StorageUploadTask uploadTask = reference.putData(imageData);
      StorageTaskSnapshot storageTaskSnapshot;

      // Release the image data
      asset.releaseOriginal();

      StorageTaskSnapshot snapshot = await uploadTask.onComplete;
      if (snapshot.error == null) {
        storageTaskSnapshot = snapshot;
        final String downloadUrl = await storageTaskSnapshot.ref.getDownloadURL();
        uploadUrls.add(downloadUrl);

        print('Upload success');
      } else {
        print('Error from image repo ${snapshot.error.toString()}');
        throw ('This file is not an image');
      }
    }), eagerError: true, cleanUp: (_) {
     print('eager cleaned up');
    });

    return uploadUrls;
}

Solution 2

These solutions does not work with firebase_storage: ^5.0.1 as await uploadTask.onComplete; is not applicable anymore. Please suggest any other solution if you upgraded your app. Thanks

Solution 3

I tried the marked answer didnt work for me so i dug deep and managed to do it with a for loop

 List<File> _imageList = List();
//add selected images to list
 _imageList.add(_image);
      Future uploadMultipleImages() async {

    List<String> _imageUrls = List();




    try {
      for (int i = 0; i < _imageList.length; i++) {
        final StorageReference storageReference = FirebaseStorage().ref().child("multiple2/$i");

        final StorageUploadTask uploadTask = storageReference.putFile(_imageList[i]);

        final StreamSubscription<StorageTaskEvent> streamSubscription =
            uploadTask.events.listen((event) {
          // You can use this to notify yourself or your user in any kind of way.
          // For example: you could use the uploadTask.events stream in a StreamBuilder instead
          // to show your user what the current status is. In that case, you would not need to cancel any
          // subscription as StreamBuilder handles this automatically.

          // Here, every StorageTaskEvent concerning the upload is printed to the logs.
          print('EVENT ${event.type}');
        });

        // Cancel your subscription when done.
        await uploadTask.onComplete;
        streamSubscription.cancel();

        String imageUrl = await storageReference.getDownloadURL();
        _imageUrls.add(imageUrl); //all all the urls to the list
      }
      //upload the list of imageUrls to firebase as an array
      await _firestore.collection("users").document("user1").setData({
        "arrayOfImages": _imageUrls,
      });
    } catch (e) {
      print(e);
    }
  }

you can check more from this github project

Share:
7,622
Mohamed Mohamed
Author by

Mohamed Mohamed

Updated on December 07, 2022

Comments

  • Mohamed Mohamed
    Mohamed Mohamed over 1 year

    I'm trying to upload n number of photos to Firebase Storage and save those URLs in an array inside Firestore, but I am not able to get the downloadURL() or I do not know where to find it rather. I've checked other answers but those were for single files, I'm trying to upload a batch and store the URLs together instead of uploading on and storing the URL to Firestore and so on and so forth...

    CODE:

    _uploadImages(String userID, String productID, List<File> images, Function onSuccess(List<String> imageURLs), Function onFailure(String e)) {
        List<String> imageURLs = [];
        int uploadCount = 0;
    
        StorageReference storeRef = FirebaseStorage.instance.ref().child('Products').child(userID).child(productID).child(uploadCount);
        StorageMetadata metaData = StorageMetadata(contentType: 'image/png');
    
        images.forEach((image) {
          storeRef.putFile(image, metaData).onComplete.then((snapshot) {
            STUCK AT THIS POINT SINCE THE SNAPSHOT DOESN'T SHOW THE URL OPTION...
            //imageURLs.add(snapshot. )
            uploadCount++;
    
            if (uploadCount == images.length) {
              onSuccess(imageURLs);
            }
          });
        });
      }
    
  • Saif Hakeem
    Saif Hakeem almost 5 years
    If you're using multi_image_picker, asset.release is removed. Quoting plugin change_log "Removed Asset.releaseThumb, Asset.releaseOriginal and Asset.release methods, as they are no longer needed."
  • BIS Tech
    BIS Tech over 4 years
    I think better to use multiple fileNames too