3

I'm getting an error : storage/object-not-found when trying to upload a large image file in Google Cloud Storage using RxFire.

They say the image is not found in the bucket but when I check, i see them!

I tested with small images (100kb likely...) works great.

But tried with > 500kb images, doesn't work...

upload$
  .pipe(
    switchMap((event: any) => {
      const name = Math.random().toString(36).substring(5);
      const blob = event.target.files[0];
      const type = blob.type.replace('image/', '');
      const ref = storage.ref(`uploads/test/${name}.${type}`);
      return put(ref, blob);
    }),
    map(snapshot => snapshot),
    filter(snapshot => snapshot.totalBytes === snapshot.bytesTransferred),
    mergeMap(snapshot => getDownloadURL(snapshot.ref))
  )
  .subscribe(url => {
    console.log('Results', url)
  }, (error) => {
    // ERROR HERE
    console.log('error', error)
  })

Expected result : Upload working with big images

Actual results : Error

Uncaught t {code_: "storage/object-not-found", message_: "Firebase . 
Storage: Object 'uploads/test/7xpbilmb.jpeg' does not exist.", 
serverResponse_: "{↵  "error": {↵    "code": 404,↵    "message": 
"Not Found.  Could not get object"↵  }↵}", name_: "FirebaseError"}
Cœur
  • 37,241
  • 25
  • 195
  • 267
MichelDelpech
  • 853
  • 8
  • 36
  • I'd guess that getDownloadURL is somehow getting called before the upload is fully complete. – Doug Stevenson Jan 20 '19 at 17:17
  • Hey, yeah that's wierd.. with 8kb files, it works, but when I reach around 300kb, this error appears. I'm waiting bytes transferred === the total bytes.. but maybe thats not enough? – MichelDelpech Jan 20 '19 at 17:22
  • 2
    With the regular javascript APIS, you wait for the UploadTask promise to resolve, or you wait for the UploadTaskSnapshot state to be "SUCCESS". – Doug Stevenson Jan 20 '19 at 17:28
  • 1
    alright, i'm using promises now with the regular .put() method and it works fine... thanks. But if someone has the same problem with RxJs, feel free to share :D – MichelDelpech Jan 20 '19 at 17:37
  • I've had that problem when `AngularFireStorageReference` and `AngularFireUploadTask` referred to a different file name due to my mistake including in one of them timestamp, and in other not. Finally, variable declaration such as `const fileName = file.name + '_' + Date.now();` and reference in both of these objects created by `AngularFireStorageReference` and `AngularFireUploadTask` did the trick. – Daniel Danielecki Dec 30 '20 at 18:07

1 Answers1

5

You can do it both ways.

  1. Promises

     storageRef.put(blob, {customMetadata}).then(data => {
                    data.ref.getDownloadURL().then(url => {
                        // do whatever you want with url
                    });
                });
    
  2. Observables

    downloadURL = new Subject();
    this.downloadURL.pipe(
                    map(obs => obs),
                    concatAll()
                ).subscribe(url => {
                    // do whatever you want with url
                });
    
    let task = ref.put(blob, {customMetadata});
    task.snapshotChanges().pipe(
                    finalize(() => this.downloadURL.next(ref.getDownloadURL()))
                ).subscribe();
    

This should be enough to get you your downloadURL. In case you wanna track upload progress with observables, here's the code for that:

task.percentageChanges().subscribe(progress => {
                console.log('upload progress: ', progress);
                if (res >= 100) {
                    // HOORAY!
                }
            });
T. Dayya
  • 690
  • 11
  • 12