用户已登录但无法通过 AngularFire 访问 Firebase 存储
User is logged in yet cannot access Firebase Storage through AngularFire
我正在通过 angularfire 使用 Angular 和 Firebase 开发一个网络应用程序。我有一个为用户处理身份验证过程的服务,名为 HandleAuthService。我想允许用户上传他们自己的头像。我将个人资料图片存储在 Firebase 存储中的唯一文件路径下。他们的图片存放的文件路径在:
UID/displayPicture/.
当用户上传图片时,它会出现在他们唯一路径下的 Firebase 存储中。但是,当我尝试下载图片以便显示时,我 运行 遇到 403 错误,它声称用户没有读取或写入权限。
错误
ERROR FirebaseError: Firebase Storage: User does not have permission to access 'USER_ID/displayPicture.jpg'. (storage/unauthorized)
{
"error": {
"code": 403,
"message": "Permission denied. Please enable Firebase Storage for your bucket by visiting
the Storage tab in the Firebase Console and ensure
that you have sufficient permission to
properly provision resources."
}
}
这是我的存储规则(我没有更改):
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
我尝试删除 if request.auth !=null;
但它仍然产生相同的错误。
以下是 HandleAuthService 代码的片段:
constructor(private fireAuth: AngularFireAuth, private ngZone: NgZone, private router: Router) {
//I create an observable for other components to subscribe to in order to get
//key information such as the uid
this.currentUser$ = this.fireAuth.authState.pipe(
take(1),
map(user => {
if (user) {
return {uid: user.uid, email:user.email, displayName:user.displayName}
} else {
return null;
}
})
);
}
//to login at the very beginning, the users may do so through google
googleLogin(provider:any) {
return this.fireAuth.signInWithPopup(provider)
.then((result)=> {
this.ngZone.run(() => {
this.router.navigate(['data']);
});
this.setUser(result.user);
})
.catch((error) => {
console.log(error);
})
}
然后,在每个组件中,我订阅 this.currentUser$
以访问用户的 authState 数据。这一直适用于所有其他组件。
在我显示头像的组件中,picture.component.ts:
constructor(private handleAuth:HandleAuthService, private storage: AngularFireStorage, private crowboxService:CrowboxdbService) { }
//in this function I try to get the profile picture from the Firebase Storage
ngOnInit(): void {
//Subscribe to the user auth state observable and wait
//to get the UID to proceed - then get the user's profile picture to be displayed
this.handleAuth.currentUser$
.subscribe(user => {
this.userId = user.uid;
this.getProfilePicture();
});
}
//the function to upload the profile picture - invoked by the click of a button
uploadFile(event:any) {
const file = event.target.files[0];
this.filePath = `${this.userId}/displayPicture`;
const task = this.storage.upload(this.filePath, file);
}
//the function to get the profile picture
getProfilePicture() {
const ref = this.storage.ref(`${this.userId}/displayPicture.jpg`);
this.profileUrl = ref.getDownloadURL();
}
picture.component.ts的HTML观点:
<div id="imageContainer">
IMAGE GOES HERE
<img alt="Profile Picture" [src]="profileUrl | async" />
<div>
<input type="file" (change)="uploadFile($event)">
</div>
</div>
如果用户可以上传图片,为什么我检索不到图片?如何确保用户已登录?
我还想补充一点,我也设置了路由守卫:
const routes: Routes = [
{ path:'', redirectTo:'/home', pathMatch:'full' },
{ path:'home', component:HomeComponent},
{ path:'data', component:DataComponent, canActivate: [AngularFireAuthGuard] },
{ path:'troubleshoot', component:TroubleshootComponent, canActivate: [AngularFireAuthGuard] },
{ path:'profile', component:ProfileComponent, canActivate: [AngularFireAuthGuard] },
];
问题在于 URL 的检索方式。这是根据 AngularFire Documentation 的正确方法:
picture.component.ts
uploadFile(event:any) {
const file = event.target.files[0];
this.filePath = `/Users/${this.userId}/profilePicture`;
const fileRef = this.storage.ref(this.filePath);
const task = this.storage.upload(this.filePath, file);
this.$taskSub = task.snapshotChanges().pipe(
finalize(() => {
//Get the download url of the photo that has been stored
//in the storage
this.downloadURL = fileRef.getDownloadURL();
this.$downloadURLSub = this.downloadURL.subscribe(result => {
this.profileUrl = result;
})
}))
.subscribe();
}
在这段代码中,我在 Firebase 项目中订阅了任务的更改,并从可观察的任务中检索下载 URL。 URL 现在可用于检索图像,如下所示。
picture.component.html
<img src="{{profileUrl}}" alt="Profile Picture" class="imageContainer">
我正在通过 angularfire 使用 Angular 和 Firebase 开发一个网络应用程序。我有一个为用户处理身份验证过程的服务,名为 HandleAuthService。我想允许用户上传他们自己的头像。我将个人资料图片存储在 Firebase 存储中的唯一文件路径下。他们的图片存放的文件路径在: UID/displayPicture/.
当用户上传图片时,它会出现在他们唯一路径下的 Firebase 存储中。但是,当我尝试下载图片以便显示时,我 运行 遇到 403 错误,它声称用户没有读取或写入权限。
错误
ERROR FirebaseError: Firebase Storage: User does not have permission to access 'USER_ID/displayPicture.jpg'. (storage/unauthorized)
{
"error": {
"code": 403,
"message": "Permission denied. Please enable Firebase Storage for your bucket by visiting
the Storage tab in the Firebase Console and ensure
that you have sufficient permission to
properly provision resources."
}
}
这是我的存储规则(我没有更改):
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
我尝试删除 if request.auth !=null;
但它仍然产生相同的错误。
以下是 HandleAuthService 代码的片段:
constructor(private fireAuth: AngularFireAuth, private ngZone: NgZone, private router: Router) {
//I create an observable for other components to subscribe to in order to get
//key information such as the uid
this.currentUser$ = this.fireAuth.authState.pipe(
take(1),
map(user => {
if (user) {
return {uid: user.uid, email:user.email, displayName:user.displayName}
} else {
return null;
}
})
);
}
//to login at the very beginning, the users may do so through google
googleLogin(provider:any) {
return this.fireAuth.signInWithPopup(provider)
.then((result)=> {
this.ngZone.run(() => {
this.router.navigate(['data']);
});
this.setUser(result.user);
})
.catch((error) => {
console.log(error);
})
}
然后,在每个组件中,我订阅 this.currentUser$
以访问用户的 authState 数据。这一直适用于所有其他组件。
在我显示头像的组件中,picture.component.ts:
constructor(private handleAuth:HandleAuthService, private storage: AngularFireStorage, private crowboxService:CrowboxdbService) { }
//in this function I try to get the profile picture from the Firebase Storage
ngOnInit(): void {
//Subscribe to the user auth state observable and wait
//to get the UID to proceed - then get the user's profile picture to be displayed
this.handleAuth.currentUser$
.subscribe(user => {
this.userId = user.uid;
this.getProfilePicture();
});
}
//the function to upload the profile picture - invoked by the click of a button
uploadFile(event:any) {
const file = event.target.files[0];
this.filePath = `${this.userId}/displayPicture`;
const task = this.storage.upload(this.filePath, file);
}
//the function to get the profile picture
getProfilePicture() {
const ref = this.storage.ref(`${this.userId}/displayPicture.jpg`);
this.profileUrl = ref.getDownloadURL();
}
picture.component.ts的HTML观点:
<div id="imageContainer">
IMAGE GOES HERE
<img alt="Profile Picture" [src]="profileUrl | async" />
<div>
<input type="file" (change)="uploadFile($event)">
</div>
</div>
如果用户可以上传图片,为什么我检索不到图片?如何确保用户已登录?
我还想补充一点,我也设置了路由守卫:
const routes: Routes = [
{ path:'', redirectTo:'/home', pathMatch:'full' },
{ path:'home', component:HomeComponent},
{ path:'data', component:DataComponent, canActivate: [AngularFireAuthGuard] },
{ path:'troubleshoot', component:TroubleshootComponent, canActivate: [AngularFireAuthGuard] },
{ path:'profile', component:ProfileComponent, canActivate: [AngularFireAuthGuard] },
];
问题在于 URL 的检索方式。这是根据 AngularFire Documentation 的正确方法:
picture.component.ts
uploadFile(event:any) {
const file = event.target.files[0];
this.filePath = `/Users/${this.userId}/profilePicture`;
const fileRef = this.storage.ref(this.filePath);
const task = this.storage.upload(this.filePath, file);
this.$taskSub = task.snapshotChanges().pipe(
finalize(() => {
//Get the download url of the photo that has been stored
//in the storage
this.downloadURL = fileRef.getDownloadURL();
this.$downloadURLSub = this.downloadURL.subscribe(result => {
this.profileUrl = result;
})
}))
.subscribe();
}
在这段代码中,我在 Firebase 项目中订阅了任务的更改,并从可观察的任务中检索下载 URL。 URL 现在可用于检索图像,如下所示。
picture.component.html
<img src="{{profileUrl}}" alt="Profile Picture" class="imageContainer">