Вставить / обновить изображение профиля пользователя с помощью Firebase Storage и Firebase - PullRequest
0 голосов
/ 30 мая 2018

Когда пользователь обновляет фотографию своего профиля, мне нужно загрузить его фотографию в Firebase Storage и немедленно получить URL-адрес для загрузки, чтобы обновить коллекцию своего профиля.

В другом сценарии, когда пользователь обновляет свой профиль, он делаетне изменять свою фотографию профиля, поэтому у меня нет imageData, а также не нужно загружать его фотографию, просто обновите информацию о его профиле.

Мой saveProfile() метод:

if (this.profileForm.valid) {
....

  //Check if the user change his picture. If yes, the userProfilePicture has data.
  If (userProfilePicture) {
    //upload the picture to firestorage
      const path = `/profile/${this.profile.id}.jpg`;
      const task =  this.afStorage
        .ref(path)
        .putString(imageData, 'base64', { contentType: 'image/jpeg' });

   // subscribe to download url
      task.downloadURL().subscribe(
        url => {
          //updating profileUrl in the form
          this.profileForm.patchValue({ avatar: url });
      //Doing the update in Firestore
      this.afs.doc(`/profile/${id}`).update(this.profileForm.value);
      });

  }
  Else {
     // just update the profile information
     this.afs.doc(`/profile/${id}`).update(this.profileForm.value);
  }

}

Я хочу избежать дублирования кода обновления в 2 местах.Есть ли более удобный способ добиться этого?Может быть, если есть способ сделать обновление только тогда, когда у меня есть downloadUrl (в 2 сценариях), что-то вроде этого:

If (userProfilePicture) {
  //upload the picture
  //subscribe to get the download url
}

//AWAIT for the subscribe to return the download URL and when the download URL is available then update
?? How to do this

//update the profile information with the new or existent download URL
await??? this.afs.doc(`/profile/${id}`).update(this.profileForm.value); 

1 Ответ

0 голосов
/ 30 мая 2018

FYI downloadURL() на задании устарела в 5.0, вам нужно будет использовать задание на ref после завершения загрузки;так что вам нужно сохранить ссылку на это:

const path = `/profile/${this.profile.id}.jpg`;
const ref = this.afStorage.ref(path);
const task =  ref.putString(imageData, 'base64', { contentType: 'image/jpeg' });

task.snapshotChanges().pipe(
  filter(snap => snap.state === storage.TaskState.SUCCESS)
  switchMap(() => ref.getDownloadURL())
).subscribe(url => {
  ...
})

Что касается сокращения дублирующегося кода, просто использовать обновление - это нормально;поскольку это только обновит указанные поля.Просто оставьте изображение профиля вне профиля.

// if there's a profile picture to upload, do so
if (userProfilePicture) {
  const path = `/profile/${this.profile.id}.jpg`;
  const ref = this.afStorage.ref(path);
  const task =  ref.putString(imageData, 'base64', { contentType: 'image/jpeg' });

  task.snapshotChanges().pipe(
    filter(snap => snap.state === storage.TaskState.SUCCESS)
    switchMap(() => ref.getDownloadURL())
  ).subscribe(profilePicture => {
    this.afs.doc(`/profile/${id}`).update({profilePicture});
  })
}

// also just update the rest of the profile, update is non-destructive and only overwrites the fields specified
this.afs.doc(`/profile/${id}`).update(this.profileForm.value); 
...