使用 Firebase 存储和 Firebase 插入/更新用户个人资料图片
Insert / Update user profile picture using Firebase Storage and Firebase
当用户更新您的个人资料图片时,我需要将他的照片上传到 Firebase 存储并立即检索下载 URL 以更新他的个人资料 collection。
另一种情况下,当用户更新他的个人资料时,他没有改变他的个人资料图片,所以我没有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);
}
}
我想避免重复更新代码。有没有更方便的方法来实现这一目标?
也许,如果我在有可用的 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);
仅供参考 downloadURL()
on task 在 5.0 中已贬值,您需要在上传完成后使用 on 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 => {
...
})
关于减少重复代码,用update就可以了;因为那只会更新指定的字段。只需将个人资料图片从 profileForm 中删除即可。
// 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);
当用户更新您的个人资料图片时,我需要将他的照片上传到 Firebase 存储并立即检索下载 URL 以更新他的个人资料 collection。
另一种情况下,当用户更新他的个人资料时,他没有改变他的个人资料图片,所以我没有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);
}
}
我想避免重复更新代码。有没有更方便的方法来实现这一目标? 也许,如果我在有可用的 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);
仅供参考 downloadURL()
on task 在 5.0 中已贬值,您需要在上传完成后使用 on 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 => {
...
})
关于减少重复代码,用update就可以了;因为那只会更新指定的字段。只需将个人资料图片从 profileForm 中删除即可。
// 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);