AngularFire storage task observable never complete

2019-07-22 14:18发布

问题:

I am uploading a camera gallery image to firebase successfully, however I am unable to getDownloadURL() as the AngularFire storage task observable never completes.

I have consulted the documentation following the 'Monitoring upload percentage' - Example Usage here

Please can you kindly advise what I am doing wrong or recommend an alternative approach. Thanks.

async onCamera(){
      try{
          const options: CameraOptions = {
          quality: 100,
          targetHeight:500,
          targetWidth:500,
          allowEdit: true,
          correctOrientation: true,
          sourceType: this.camera.PictureSourceType.PHOTOLIBRARY,
          destinationType: this.camera.DestinationType.DATA_URL,
          encodingType: this.camera.EncodingType.JPEG,
          mediaType: this.camera.MediaType.PICTURE
        }
        const imageData = await this.camera.getPicture(options);
        const image = 'data:image/jpeg;base64,' + imageData;
        const id = Math.random().toString(36).substring(2);
        const user = this.authenticatorService.getUser();
        const fileRef = this.afStorage.ref(user.uid + '/images/categories/'+id);
        const task = fileRef.putString(image, 'data_url');
        console.log('Done! - I can see this comment successfully logged to the terminal');
        //---------------------------------
        // But this Observable never completes?....
        //---------------------------------
        task.snapshotChanges().pipe(
          finalize(() => {
            console.log('Sequence complete'); // Execute when the observable completes: never logged
            this.downloadURL = fileRef.getDownloadURL();
            this.downloadURL.subscribe(url=> this.imageUrl=url);
            console.log('My ImageUrl' + this.imageUrl); // Never logged to terminal?
          }));

        console.log('Finished! - I can see this comment successfully logged to the terminal');
      } catch(e) {
        console.error(e);
        this.errorMessage = JSON.stringify(e);
        console.log(this.errorMessage);
      }
    }

Relevant Imports

import { AngularFireStorage, AngularFireStorageReference, AngularFireUploadTask } from '@angular/fire/storage';
    import { Observable } from 'rxjs/Observable';
    import { Camera, CameraOptions} from '@ionic-native/camera/ngx';
    import { finalize } from 'rxjs/operators';

Ionic Native 5 Reference: https://blog.ionicframework.com/help-test-ionic-native-5/

Relevant Dependencies

"dependencies": {
    "@angular/animations": "6.1.0",
    "@angular/common": "6.1.0",
    "@angular/compiler": "6.1.0",
    "@angular/compiler-cli": "6.1.0",
    "@angular/core": "6.1.0",
    "@angular/fire": "^5.1.0",
    ....
    "@ionic-native/camera": "^5.0.0-beta.22",
    "@ionic-native/core": "^5.0.0-beta.22",
    ...
    "cordova-plugin-camera": "~4.0.3",
    ...
    "firebase": "^5.5.9",
    "ionic-angular": "3.9.2",
    "promise-polyfill": "^8.1.0",
    "rxjs": "^6.3.3",
    "rxjs-compat": "^6.3.3",
    "cordova-android": "~7.1.4"
  },

回答1:

You look like you're 99.9% of the way there, nice job on this one! And thanks for providing the links to the docs. I think the reason that the finalize() is never firing is because you aren't subscribing to the .snapshotChanges(). Without .subscribe() your code won't actually listen to the changes fired off by task.snapshotChanges().

In the example you found, notice that there is a .subscribe() stuck on after the .pipe():

// get notified when the download URL is available
task.snapshotChanges().pipe(
    finalize(() => this.downloadURL = fileRef.getDownloadURL() )
)
.subscribe()

So your code should be:

//---------------------------------
// But this Observable never completes?....
//---------------------------------
task.snapshotChanges().pipe(
    finalize(() => {
        this.downloadURL = fileRef.getDownloadURL();
        console.log('My ImageUrl' + this.downloadURL);
    })
).subscribe();