0

I have image upload feature in my Xamarin.iOS application. I have stored this uploaded image(s) in firebase storage. My files gets uploaded to firebase storage successfully, but the issue is:

When I am trying to get all images using listAll() method of firebase storage it not return all images until the folder have images >= 2.

Code to upload image on firebase storage:

private void ImagePicker_FinishedPickingMedia(object sender, UIImagePickerMediaPickedEventArgs e)
{
    if (e.Info[UIImagePickerController.MediaType].ToString() == "public.image")
    {
        NSData imgData = new NSData();
        imgData = e.OriginalImage.AsJPEG();

        Guid uniqId = Guid.NewGuid(); // use - uniqId.ToString()

        FirebaseClient.Instance.UploadAdventurePhoto(imgData, this.Adventure.Id, uniqId.ToString());

        //(Path of folder - gs://myapp.appspot.com/adventures/00ac45a3-7c92-4335-a4b8-b9b705c4dd72)
        StorageReference photsUrl = Storage.DefaultInstance.GetReferenceFromUrl($"gs://myapp.appspot.com/adventures/{this.Adventure.Id}");
        photsUrl.ListAll(this.Handler);
    }
    this.imagePicker.DismissViewController(true, null);
}

// Add image to Firestore collection's Document.
private async void Handler(StorageListResult result, NSError arg2)
{
    foreach (var image in result.Items)
    {
        // Logic to append image to Firestore document.
    }
}

/// <param name="imgData">Selected image that needs to be stored on storage.</param>
/// <param name="adventureId">Name of the folder.</param>
/// <param name="imageName">By this name image will get stored in folder.</param>
public void UploadAdventurePhoto(NSData imgData, string adventureId, string imageName)
{
    StorageReference adventurePictureRef = Storage.DefaultInstance.GetReferenceFromPath($"adventures/{adventureId}/{imageName}");
    StorageMetadata metaData = new StorageMetadata();
    metaData.ContentType = "image/jpg";
    adventurePictureRef.PutData(imgData, metaData);
}

After first image get uploaded, image get uploaded successfully but when handler gets called it gives this response:

enter image description here

But after this when I upload 2nd image that time it give Firebase.Storage.StorageReference1 in response:

enter image description here

Means if there are two images then only it returns url reference. How to fix this issue?

I have already added rules_version = '2'; in storage rules.

Divyesh
  • 2,085
  • 20
  • 35

1 Answers1

1

Haven't got the solution for listAll() but I have got the work around for this problem.

What I was trying is to get all the images from firebase storage using listAll(), but in that I am getting this issue. So now instead of listAll() I am using PutData() method's completion handler.

The completion handler will provide you the Metadata of an uploaded image. From this meta data we can get image directly like this: metadata.Name

Here is how I have fix the problem by adding completion handler in UploadAdventurePhoto() method:

private void UploadAdventurePhoto(NSData imgData, string folderName, string imageName)
{
    StorageReference adventurePictureRef = Storage.DefaultInstance.GetReferenceFromPath($"adventures/{folderName}/{imageName}");
    StorageMetadata metaData = new StorageMetadata();
    metaData.ContentType = "image/jpeg";
    adventurePictureRef.PutData(imgData, metaData, this.HandleStorageGetPutUpdateCompletion);
}

private async void HandleStorageGetPutUpdateCompletion(StorageMetadata metadata, NSError error)
{
    if (error != null)
    {
        // Uh-oh, an error occurred!
        return;
    }

    var url = metadata.Name;
    var downloadUrl = metadata.Path;
    Debug.WriteLine($"Image url - {url}\n Path-{downloadUrl}");

    CollectionReference collectionRef = Firestore.SharedInstance.GetCollection(FirebaseClient.AdventuresCollection);
    var docRef = collectionRef.GetDocument(this.Adventure.Id);

    var keys = new NSString[]
    {
        new NSString($"{AdventureBase.PhotoPropName}"),
    };
    var value = new NSObject[]
    {
        new NSString(url),
    };
    var objects = new NSObject[]
    {
        FieldValue.FromArrayUnion(value),
    };

    var dict = new NSDictionary<NSString, NSObject>(keys, objects);

    await docRef.SetDataAsync(dict, true);
    docRef.AddSnapshotListener(this.UpdateDataHandler);
}

private async void UpdateDataHandler(DocumentSnapshot snapshot, NSError error)
{
    if (error != null)
    {
        // something went wrong
        Debug.WriteLine($"Error - {error.Description}");
        return;
    }
    Toast.MakeToast("Image uploaded successfully").Show();
}
Divyesh
  • 2,085
  • 20
  • 35