0

I am trying to upload multiple files to firebase storage and their urls to Firestore using a for loop. If I try to upload 3 files,then all 3 are uploaded to the firebase storage but the url of only the first file is added to Firestore. I don't see any problem in my for loop as such, so how should I fix this?

 @Override
 protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
     super.onActivityResult(requestCode, resultCode, data);

     if (requestCode == 101 && resultCode == RESULT_OK) {

         final String folderName = intent.getStringExtra("folderName");

         if (data.getClipData() != null) {
             //multiple files

             int numItemSelected = data.getClipData().getItemCount();

             for (int i = 0; i < numItemSelected; i++) {

                 Uri pdfUri = data.getClipData().getItemAt(i).getUri();
                 fileName = getFileName(pdfUri);

                 pdfNameList.add(fileName);
                 pdfUrlList.add(pdfUri.toString());

                 StorageReference pdfRef = storageReference.child(folderName + "/" + fileName);
                 pdfRef.putFile(pdfUri)
                     .addOnSuccessListener(new OnSuccessListener < UploadTask.TaskSnapshot > () {
                         @Override
                         public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                             Toast.makeText(MainActivity.this, "File Uploaded!", Toast.LENGTH_SHORT).show();

                             Task < Uri > uriTask = taskSnapshot.getStorage().getDownloadUrl();
                             while (!uriTask.isComplete());
                             Uri uri = uriTask.getResult();

                             Map < String, Object > map = new HashMap < > ();
                             map.put("url", String.valueOf(uri));
                             map.put("name", fileName);
                             DocumentReference documentReference =
                                 db.collection(folderName).document(fileName);

                             documentReference.set(map)
                                 .addOnSuccessListener(new OnSuccessListener < Void > () {
                                     @Override
                                     public void onSuccess(Void aVoid) {
                                         Log.d("TEST", "onSuccess: Task was  successful");

                                     }
                                 })
                                 .addOnFailureListener(new OnFailureListener() {
                                     @Override
                                     public void onFailure(@NonNull Exception e) {
                                         Log.d("TEST", "onFailure: Task was not successful" +
                                             e.getLocalizedMessage() + "  " + e.getMessage());
                                     }
                                 });

                         }
                     })
                     .addOnFailureListener(new OnFailureListener() {
                         @Override
                         public void onFailure(@NonNull Exception e) {
                             Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                         }
                     });


             }
             Log.d("size", "onActivityResult: " + pdfNameList.size()); //logs the correct size

         } else if (data.getData() != null) {
             //selected single file
             //working code,skipped from here   

         }

     }
 }

Edit : Only the last document is being uploaded to Firestore. If I am uploading two files then the value of i (variable of for loop) is 2 just after putting strings in my map

Edit: My problem is similar to this, but I can't seem to understand the solution

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Chirag
  • 98
  • 8
  • 1
    How is this different from the question you posted yesterday: [Uploading multiple pdf files to Firebase storage - Android](https://stackoverflow.com/questions/63012301/uploading-multiple-pdf-files-to-firebase-storage-android)? – Frank van Puffelen Jul 22 '20 at 23:18
  • @FrankvanPuffelen in that question , I was having problem in locally picking up multiple files. The answer I was expecting for that was "Making use of `data.getClipData` and `data.getData` . Here I'm having problem in uploading only the URLs to Firestore. If you think these questions are same, I can delete either of them – Chirag Jul 23 '20 at 05:38
  • In that question I thought I had to use a for loop enclosing my entire code, but that wouldn't work properly. I have to make use of clipData – Chirag Jul 23 '20 at 05:41
  • @FrankvanPuffelen can you look at this again please – Chirag Jul 23 '20 at 10:45

1 Answers1

0

The problem is that you are doing multiple sequenced asynchronous operations (upload to Storage and adding data to firestore) in a synchronous way in your loop and that causes the following behavior (example):

The second upload to Storage triggers before the first operation to Firestore has been completed, and this causes the fileName variable that is being used for the Firestore operation to be populated with value of the next upload.

My suggestion to fix the issue you are facing would be to either not do the operations in sequence, eg. upload everything into storage and only then add everything to firestore, or populate the part of your map that depends on the filename variable right after it's value has been populated and not in the onSuccess handler.

Ralemos
  • 5,571
  • 2
  • 9
  • 18
  • `upload everything into storage and only then add everything to firestore` . How do I do this? I made a serperate for loop after my first for loop just to upload to my firestore by that doesn't work. Although I'm sure you understand my problem – Chirag Jul 23 '20 at 20:02
  • I would say that you should create a loop that uploads everything to storage and prepares the data to be uploaded to firestore based on each individual `filename` generated, and only when its finished, open a second loop to add data to firestore. That way you are guaranteed that no data will be lost due to synchronicity. – Ralemos Jul 27 '20 at 15:05