firebase / firebase-android-sdk

Firebase Android SDK
https://firebase.google.com
Apache License 2.0
2.27k stars 574 forks source link

Firebase E/StorageException: StorageException has occurred. Object does not exist at location #3156

Closed varun7952 closed 2 years ago

varun7952 commented 2 years ago

[REQUIRED] Step 2: Describe your environment

[REQUIRED] Step 3: Describe the problem

Steps to reproduce:

I am trying to upload 4 different images to firebase storage, my code works with single image but whenever i tried to upload multiple image i get

E/StorageException: StorageException has occurred.
    Object does not exist at location.
     Code: -13010 HttpResult: 404
2021-11-18 22:45:16.584 com.example.test E/StorageException: {  "error": {    "code": 404,    "message": "Not Found."  }}
    java.io.IOException: {  "error": {    "code": 404,    "message": "Not Found."  }}
        at com.google.firebase.storage.network.NetworkRequest.parseResponse(NetworkRequest.java:445)
        at com.google.firebase.storage.network.NetworkRequest.parseErrorResponse(NetworkRequest.java:462)
        at com.google.firebase.storage.network.NetworkRequest.processResponseStream(NetworkRequest.java:453)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(NetworkRequest.java:272)
        at com.google.firebase.storage.network.NetworkRequest.performRequest(NetworkRequest.java:289)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(ExponentialBackoffSender.java:76)
        at com.google.firebase.storage.internal.ExponentialBackoffSender.sendWithExponentialBackoff(ExponentialBackoffSender.java:68)
        at com.google.firebase.storage.GetDownloadUrlTask.run(GetDownloadUrlTask.java:77)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)

This is my code to upload images to firebase storage and even after getting errors i can see images on firebase Storage but i am getting error on app.

private synchronized void UploadToFireBaseStorage(ArrayList<String> filePath,int type) {

        final ArrayList<String> multipleImages = new ArrayList<>();
        Log.d(TAG,"Size of File at Upload Method "+filePath.size());

        if (filePath.size()==0){
            return;
        }

        Uri fileUri = null;

        for (String s : filePath) {
            if (s.contains(".jpg")) {
                    fileUri = Uri.fromFile(new File(s));
                } else {
                    fileUri = Uri.parse(s);
                }

            StorageReference mStorageReference = FirebaseStorage.getInstance().getReference();
            Log.d(TAG, "UploadToFireBaseStorage: StorageRef "+mStorageReference);

            storageReference = mStorageReference.child("Photos").child(fileUri.getLastPathSegment());

            Log.d(TAG, "UploadToFireBaseStorage: Storage Reference "+storageReference);
            Log.d(TAG, "UploadToFireBaseStorage: File URI = "+fileUri);
            String finalAttachmentType = attachmentType;
            String finalUploadFolder = uploadFolder;
            storageReference.putFile(fileUri).addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(@NonNull Uri uri) {
                            Log.d(TAG, "Image Uploaded ");
                            Log.d(TAG, "onSuccess: URI Uploaded == "+uri);

                        }
                    });
                }
            }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                    double progress = 100.0 * taskSnapshot.getBytesTransferred() / (double) taskSnapshot.getTotalByteCount();
                    Log.d(TAG, "Upload is " + progress + "% done");

                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.d(TAG, "onFailure: "+s);

                }
            });
        }
        Log.d(TAG,"Image List "+multipleImages.toString());
    }

These are the storage reference i got for 4 different images

Storage Reference gs://example-89902.appspot.com/Photos/Image%20IMG_1637256617899.jpg

Storage Reference gs://example-89902.appspot.com/Photos/Image%20IMG_1637256617949.jpg

Storage Reference gs://example-89902.appspot.com/Photos/Image%20IMG_1637256618132.jpg

Storage Reference gs://example-89902.appspot.com/Photos/Image%20IMG_1637256618070.jpg

My code was working properly before i made an update to 28.x.x version of firebase BOM and i also posted into Stackoverflow but i didn't get any answer yet which can resolve my issue.

Firebase Storage Rules service firebase.storage { match /b/bucket/o { match /{allPaths=**} { allow read, write; } } }

Relevant Code:

// TODO(you): code here to reproduce the problem
argzdev commented 2 years ago

Hi @varun7952, thanks for reporting. I'm unable to reproduce this issue with the code provided. May I ask if the issue always reproducible or is it inconsistent? And also just to confirm, you've already enabled Firebase Storage? Could you provide us a minimal reproducible example of your issue (MCVE)? It'll greatly help us to investigate this further.

varun7952 commented 2 years ago

Hi @varun7952, thanks for reporting. I'm unable to reproduce this issue with the code provided. May I ask if the issue always reproducible or is it inconsistent? And also just to confirm, you've already enabled Firebase Storage? Could you provide us a minimal reproducible example of your issue (MCVE)? It'll greatly help us to investigate this further.

@argzdev The issue comes up always whenever i tried to upload multiple (4 Images) images to firebase storage and the error i got in logcat E/StorageException: StorageException has occurred. Object does not exist at location. Code: -13010 HttpResult: 404 but at the same time i got the images all images (4 images) on storage The code above on andorid 30 device used to upload images on firebase storage and the above code was working fine sometime back as needed but not anymore as you can reproduce at your end.

I got the hack/answer on Stackoverflow but i still don't understand why official code also give me same error when i followed official documentation and i tried other code somewhere and strange this code @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl(); while (!urlTask.isSuccessful()); Uri downloadUrl = urlTask.getResult(); FriendlyMessage friendlyMessage = new FriendlyMessage(null, mUsername, downloadUrl.toString()); mDatabaseReference.push().setValue(friendlyMessage); }work perfectly. why the while (!urlTask.isSuccessful()); works but not the official ```

 if (task.isSuccessful()) {
            Uri downloadUri = task.getResult();
        } else {
            // Handle failures
            // ...
        }
argzdev commented 2 years ago

That is interesting, I was also using the official documentation but wasn't able to encounter this issue. Could you provide me a copy of your repo? I would like to investigate this deeper. Also just to ask, how large are the image files?

varun7952 commented 2 years ago

@argzdev Please check the this complate method which i am using to upload and if there is any thing missing i will share with you. Git Repo

argzdev commented 2 years ago

Hi @varun7952, thanks for the code. I tested your code and it works fine. However, I was able to run into the issue when I setup an incorrect proxy on my emulator. Could you check if this is the case for you?

varun7952 commented 2 years ago

@argzdev Thanks for the reply. I am testing this code on real device and without any proxy

argzdev commented 2 years ago

Hi @varun7952, given that the code is working, the most likely issue is write permissions not enabled. Could you try checking if you have the necessary permissions being requested during runtime?

Relevant code: requestPermissions(new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);

varun7952 commented 2 years ago

@argzdev I am using Android 30 Samsung device and before uploading images i am selecting images from app's custom gallery which needs permission for media access and the app always check for the permission at app startup. All the images are successfully uploaded on firebase storage but with the error i mentioned above.

I also noticed the first two images are uploading without any issue and the other 2 upload gives me same error twice i mentioned above.

It's not a permission issue for sure.

argzdev commented 2 years ago

@varun7952, since I'm unable to reproduce this issue even with the provided code, I think it would be best if you provide me a MCVE with the images for investigation, also make sure these do not contain any PII (Personal Identifiable Information).

May I ask if you've tried this with other devices or emulator and does it reproduce the same behavior?

varun7952 commented 2 years ago

@argzdev Hi, I will post code and No i didnt try on other devices, i only tried it on Android 30 (Samsung S20+)

argzdev commented 2 years ago

Okay, take your time. I'll wait for the MCVE. Thanks!

varun7952 commented 2 years ago

Hi @argzdev Please check below code on Android 30 and 30+ To reproduce the code. Images to upload in loop Image 1

Image 2

Image 3

Image 4

These images are coming to UploadToFireBaseStorage via Array of String and in for loop images uploading one by one and only first 2 images don't create any error but when it move to third it shows the error i mentioned but when i check FireBase Storage i can see all 4 images there but on app i get the error for the last 2 images.

private synchronized void UploadToFireBaseStorage(ArrayList<String> filePath,int type) {

        final ArrayList<String> multipleImages = new ArrayList<>();
        Log.d(TAG,"Size of File at Upload Method "+filePath.size());

        if (filePath.size()==0){
            return;
        }

        Uri fileUri = null;

        for (String s : filePath) {
            if (s.contains(".jpg")) {
                    fileUri = Uri.fromFile(new File(s));
                } else {
                    fileUri = Uri.parse(s);
                }

            StorageReference mStorageReference = FirebaseStorage.getInstance().getReference();
            Log.d(TAG, "UploadToFireBaseStorage: StorageRef "+mStorageReference);

            storageReference = mStorageReference.child("Photos").child(fileUri.getLastPathSegment());

            Log.d(TAG, "UploadToFireBaseStorage: Storage Reference "+storageReference);
            Log.d(TAG, "UploadToFireBaseStorage: File URI = "+fileUri);
            String finalAttachmentType = attachmentType;
            String finalUploadFolder = uploadFolder;
            storageReference.putFile(fileUri).addOnSuccessListener(this, new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    storageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                        @Override
                        public void onSuccess(@NonNull Uri uri) {
                            Log.d(TAG, "Image Uploaded ");
                            Log.d(TAG, "onSuccess: URI Uploaded == "+uri);

                        }
                    });
                }
            }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                    double progress = 100.0 * taskSnapshot.getBytesTransferred() / (double) taskSnapshot.getTotalByteCount();
                    Log.d(TAG, "Upload is " + progress + "% done");

                }
            }).addOnFailureListener(new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.d(TAG, "onFailure: "+s);

                }
            });
        }
        Log.d(TAG,"Image List "+multipleImages.toString());
    }
argzdev commented 2 years ago

Hi @varun7952, thanks for the code snippet. I found the issue in your code, it seems that you're using only a single instance of storageReference outside of your UploadToFireBaseStorage method. The reason this causes an issue is that while the file is still being uploaded, your loop changes the reference to your storageReference which causes it to break the reference to the file. To resolve this, simply reference the storageReference inside your method.

Relevant Code:

StorageReference storageReference;
storageReference = mStorageReference.child("Photos").child(fileUri.getLastPathSegment());

With that said, I'll be closing this issue, thanks.