'How can i upload multiple images to firebase in flutter and get all their download urls

Here is my upload function. My desired output is a list of all urls, but it returns an empty list. I have tried different suggested solutions, but all of them have failed.

Future<List<String>> uploadFiles(List _images) async {
  List<String> imagesUrls=[];

   _images.forEach((_image) async{
    StorageReference storageReference = FirebaseStorage.instance
        .ref()
        .child('posts/${_image.path}');
    StorageUploadTask uploadTask = storageReference.putFile(_image);
    await uploadTask.onComplete;

     imagesUrls.add(await storageReference.getDownloadURL());
     
  });
print(imagesUrls);
return imagesUrls;
}


Solution 1:[1]

I think you'll need Future.wait to ensure all futures are resolved before continuing:

Future<List<String>> uploadFiles(List<File> _images) async {
  var imageUrls = await Future.wait(_images.map((_image) => uploadFile(_image)));
  print(imageUrls);
  return imageUrls;
}

Future<String> uploadFile(File _image) async {
  StorageReference storageReference = FirebaseStorage.instance
      .ref()
      .child('posts/${_image.path}');
  StorageUploadTask uploadTask = storageReference.putFile(_image);
  await uploadTask.onComplete;

  return await storageReference.getDownloadURL();
}

Solution 2:[2]

Try this

Future<List<String>> uploadFiles(List _images) async {
  List<String> imagesUrls=[];

   _images.forEach((_image) async{
    StorageReference storageReference = FirebaseStorage.instance
        .ref()
        .child('posts/${_image.path}');
    StorageUploadTask uploadTask = storageReference.putFile(_image);
    

     imagesUrls.add(await (await uploadTask.onComplete).ref.getDownloadURL());
     
  });
print(imagesUrls);
return imagesUrls;
}

How to use this:

List<String> urls = Future.wait(uploadFiles(_images));

Solution 3:[3]

this not working. It will direct return without waiting for the foreach loop to be finished. You may use the code below:

Future<List<String>> uploadImages(List<File> images) async {
if (images.length < 1) return null;

List<String> _downloadUrls = [];

await Future.forEach(images, (image) async {
  Reference ref = FirebaseStorage.instance
      .ref()
      .child('jobPost')
      .child(getFileName(path: image));
  final UploadTask uploadTask = ref.putFile(image);
  final TaskSnapshot taskSnapshot = await uploadTask.whenComplete(() {});
  final url = await taskSnapshot.ref.getDownloadURL();
  _downloadUrls.add(url);
});

return _downloadUrls;
}

You may visit this to know what's the reason.

Solution 4:[4]

There is compile example you can get the idea

import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
import 'package:path/path.dart' as Path;

class AddImage extends StatefulWidget {
  @override
  _AddImageState createState() => _AddImageState();
}

class _AddImageState extends State<AddImage> {
  bool uploading = false;
  double val = 0;
  CollectionReference imgRef;
  firebase_storage.Reference ref;

  List<File> _image = [];
  final picker = ImagePicker();
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Add Image'),
          actions: [
            FlatButton(
                onPressed: () {
                  setState(() {
                    uploading = true;
                  });
                  uploadFile().whenComplete(() => Navigator.of(context).pop());
                },
                child: Text(
                  'upload',
                  style: TextStyle(color: Colors.white),
                ))
          ],
        ),
        body: Stack(
          children: [
            Container(
              padding: EdgeInsets.all(4),
              child: GridView.builder(
                  itemCount: _image.length + 1,
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 3),
                  itemBuilder: (context, index) {
                    return index == 0
                        ? Center(
                            child: IconButton(
                                icon: Icon(Icons.add),
                                onPressed: () =>
                                    !uploading ? chooseImage() : null),
                          )
                        : Container(
                            margin: EdgeInsets.all(3),
                            decoration: BoxDecoration(
                                image: DecorationImage(
                                    image: FileImage(_image[index - 1]),
                                    fit: BoxFit.cover)),
                          );
                  }),
            ),
            uploading
                ? Center(
                    child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Container(
                        child: Text(
                          'uploading...',
                          style: TextStyle(fontSize: 20),
                        ),
                      ),
                      SizedBox(
                        height: 10,
                      ),
                      CircularProgressIndicator(
                        value: val,
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.green),
                      )
                    ],
                  ))
                : Container(),
          ],
        ));
  }

  chooseImage() async {
    final pickedFile = await picker.getImage(source: ImageSource.gallery);
    setState(() {
      _image.add(File(pickedFile?.path));
    });
    if (pickedFile.path == null) retrieveLostData();
  }

  Future<void> retrieveLostData() async {
    final LostData response = await picker.getLostData();
    if (response.isEmpty) {
      return;
    }
    if (response.file != null) {
      setState(() {
        _image.add(File(response.file.path));
      });
    } else {
      print(response.file);
    }
  }

  Future uploadFile() async {
    int i = 1;

    for (var img in _image) {
      setState(() {
        val = i / _image.length;
      });
      ref = firebase_storage.FirebaseStorage.instance
          .ref()
          .child('images/${Path.basename(img.path)}');
      await ref.putFile(img).whenComplete(() async {
        await ref.getDownloadURL().then((value) {
          imgRef.add({'url': value});
          i++;
        });
      });
    }
  }

  @override
  void initState() {
    super.initState();
    imgRef = FirebaseFirestore.instance.collection('imageURLs');
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Henok
Solution 2 thien nguyen
Solution 3 liow
Solution 4 samad shukr