0
votes

Usecase:

The user selects multiple images from the camera roll, and adds them to their post. They type a description and title, and then choose to post. Their post appears on their user profile, with their selected images attached.

Problem:

I am creating an image blog app with Ionic 4, AngularFire2. My goal is to upload the users images to the firebase storage and download each of the image urls to reference in the Firestore database.

I can upload multiple images to the firebase storage, however I want to download each of these image urls. So far I only can download one image url. I am new to Ionic/AngularFire and I don't know what to loop or where I should loop to get the image urls in an array.

Typescript:

async uploadImageToFirebase(image){
let image_src = this.webview.convertFileSrc(image);
let randomId = Math.random().toString(36).substr(2, 5);

//uploads img to firebase storage
this.firebaseService.uploadImage(image_src, randomId)
  .then(photoURL => {
     this.image = [ photoURL ] 
     loading.dismiss();
     toast.present();
  }, err => {
     console.log(err);
  })

Service :

encodeImageUri(imageUri, callback) {
  var c = document.createElement('canvas');
  var ctx = c.getContext("2d");
  var img = new Image();
  img.onload = function () {
    var aux:any = this;
    c.width = aux.width;
    c.height = aux.height;
    ctx.drawImage(img, 0, 0);
    var dataURL = c.toDataURL("image/jpeg");
    callback(dataURL);
  };
  img.src = imageUri;
};

uploadImage(imageURI, randomId){
  return new Promise<any>((resolve, reject) => { 
    let storageRef = firebase.storage().ref();
    let imageRef  = 
      storageRef.child('image').child(randomId);
    this.encodeImageUri(imageURI, function(image64){
      imageRef.putString(image64, 'data_url')
        .then(snapshot => {  
           snapshot.ref.getDownloadURL()
             .then(res => resolve(res))
        }, err => {
          reject(err);
        })
    })
  })
}

My firestore database currently looks like this

posts : {
  Title : this is a title,
  Description: this is a description,
  image:
    [ 0 ] "https://firebasestorage.googleapis.com/v0/b/imagepost-1962c.appspot.com/o/image%2Fbak95?alt=media&token=58eb6037-4253-4dcc-b35b-8d58ddsdffss"
}

But I want it to look like

posts : {
  Title : this is a title,
  Description: this is a description,
  image:
    [ 0 ] "https://firebasestorage.googleapis.com/v0/b/imagepost-1962c.appspot.com/o/image%2Fbak95?alt=media&token=58eb6037-4253-4dcc-b35b-8d58ddsdffss"
    [ 1 ] "another image url"
    [ 2 ] "another image url"
}
1

1 Answers

-1
votes

I found something relevant to your given situation, but for Android

Source: Firebase Storage download multiple photos Urls

public static final String TAG = "eyaldebug";
public static PathGenerator pathGenerator;
public static ArrayList<String>photoURLs;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_photopackges);

    //Initialize the whole process

    photoURLs = new ArrayList<>();

    pathGenerator = new PathGenerator();

    new UrlProducer(pathGenerator);


}


/**
 * This class contains the GeneratePaths method,which responsible
 * of making new paths.
 * Also we have a simple set - get methods of the booleans.
 */

class PathGenerator {
    //start photo number
    int photoNumber = 0;
    //boolean that indicates if the path has been used already or not.
    boolean pathIsTaken = false;
    //our storage path.
    String path;

    /**
     * This method will generate a new path.
     * while path is taken , wait because we didn't use it yet.
     *
     * @param photoNumber
     */

    public synchronized String generatePath(int photoNumber) {

        while (pathIsTaken)
        {
            try {wait();} catch (Exception e) {}
        }
        this.photoNumber = photoNumber;
        path = "test/" + String.valueOf(photoNumber) + ".jpg";
        pathIsTaken = true;
        Log.e("eyaldebug", "path is :  " + path);
        return path;
    }

    /**
     * Simple set method.
     * @param value
     */

    public synchronized void setPathisSet(boolean value)
    {
        this.pathIsTaken = value;
    }

    /**
     * Unfreeze the thread, we call this method after onSucsess.
     */

    public synchronized void unfreeze( )
    {
        notifyAll();
    }

}


/**
 * Our URLProducer calls will take the paths,and will
 * send HTTP request to the storage that we'll get a
 * download URL returned.
 * later we'll be using Glide\Picasso to display those images.
 */

class UrlProducer implements Runnable {

    PathGenerator mPathGenerator;

    //initialize a String type ArrayList which will contain our URLS.
    public  ArrayList<String>photoURLs = new ArrayList<>();

    //constructor that will be called in the activity
    public UrlProducer(PathGenerator mPathGenerator) {
        this.mPathGenerator = mPathGenerator;

        Thread b = new Thread(this, "UrlProducer");
        b.start();
    }

    /**
     * Here we a simple download URL method using FirebaseStorage.
     * for the documentation for FirebaseStoarge download go to :
     *
     * https://firebase.google.com/docs/storage/android/download-files
     *
     * IF the task was successful we UNfreeze the threads so it will
     * keep sending us new URLS.
     * IF the onFailure was called the stroage is must likely empty and
     * we should stop trying to get new photos.
     */

    @Override
    public void run() {


        int photoNumber =0 ;

        while (true) {


            photoNumber ++;

            try {
                FirebaseStorage storage = FirebaseStorage.getInstance();
                StorageReference ref = storage.getReference();


                ref.child(pathGenerator.generatePath(photoNumber)).getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                    @Override
                    public void onSuccess(Uri uri) {

                        Log.e(TAG, "Success! " + uri);

                        //add the URL into the ArrayList
                        photoURLs.add(String.valueOf(uri));

                       //tell the generate method that the path has been used.
                        pathGenerator.setPathisSet(false);

                        //Unfreeze the thread so it will continue generate new paths.
                        pathGenerator.unfreeze();

                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {

                        //When onFailure is called shutdown,and output the given ArrayList.

                        Log.e(TAG,"onFailure was called , storage is empty!");
                        Log.e(TAG,"----------------------------------------");
                        for(String singleUrl :photoURLs)
                        {
                            Log.e(TAG,""+singleUrl)   ;
                        }
                    }
                });


            }catch (Exception e){e.printStackTrace();}


        }
    }

}