使用Firebase/AngularFire2获取文件下载URL时遇[object Object]错误
解决AngularFireStorage上传文件后获取URL的时机问题
嘿,你已经精准定位了问题——确实是因为在文件还在上传过程中就调用getDownloadURL()导致的异常。AngularFire的UploadTask提供了几种直观的方式来判断上传是否完成,下面给你两种实用的方案:
方案1:利用snapshotChanges() + finalize()监听上传完成
UploadTask的snapshotChanges()方法会发出上传过程中的每个状态快照,我们可以借助RxJS的finalize()操作符,在上传流程结束(无论成功或失败)时执行获取下载URL的操作:
修改你的app.component.ts中的upload方法:
import { finalize } from 'rxjs/operators'; // 记得导入这个操作符 export class AppComponent { ref: AngularFireStorageReference; task: AngularFireUploadTask; uploadProgress: Observable<number>; downloadURL: Observable<string | null>; taskName:string; id:string; uploadCompleted = false; // 新增:标记上传是否完成 uploadError: string | null = null; // 新增:存储上传错误信息 ngOnInit() { } constructor(private afStorage: AngularFireStorage){ } upload(event) { this.id = Math.random().toString(36).substring(2); this.ref = this.afStorage.ref('myURL/'+this.id); this.task = this.ref.put(event.target.files[0]); this.uploadProgress = this.task.percentageChanges(); this.uploadCompleted = false; // 重置状态 this.uploadError = null; // 监听上传状态变化,在流程结束时获取下载URL this.task.snapshotChanges().pipe( finalize(() => { this.uploadCompleted = true; // 此时上传已完成,安全获取下载URL this.downloadURL = this.ref.getDownloadURL(); }) ).subscribe( () => {}, // 可选:处理中间快照 (error) => { this.uploadError = error.message; console.error('上传过程中出错:', error); } ); } }
方案2:利用UploadTask的Promise特性等待上传完成
UploadTask本身实现了Promise接口,所以你可以直接用then()来等待上传成功,用catch()处理失败:
修改upload方法如下:
upload(event) { this.id = Math.random().toString(36).substring(2); this.ref = this.afStorage.ref('myURL/'+this.id); this.task = this.ref.put(event.target.files[0]); this.uploadProgress = this.task.percentageChanges(); this.uploadCompleted = false; this.uploadError = null; // 等待上传Promise完成 this.task.then(() => { this.uploadCompleted = true; // 上传成功后获取下载URL this.downloadURL = this.ref.getDownloadURL(); }).catch((error) => { this.uploadError = error.message; console.error('上传失败:', error); }); }
优化UI反馈(可选)
你可以在HTML中添加状态提示,让用户更清楚上传进度和结果:
<div class="card"> <div class="card-header"> Firebase Cloud Storage Angular </div> <div class="card-body"> <h5 class="card-title">Select a file for upload</h5> <input type="file" (change)="upload($event)" accept=".png, .jpg"/> <!-- 上传进度条 --> <div class="progress" *ngIf="uploadProgress | async as progress"> <div id="progress" class="progress-bar progress-bar-striped bg-success" role="progressbar" [style.width]="progress + '%'" [attr.aria-valuenow]="progress" aria-valuemin="0" aria-valuemax="100"> </div> </div> <!-- 错误提示 --> <div *ngIf="uploadError" class="alert alert-danger mt-3" role="alert"> 上传失败:{{uploadError}} </div> <!-- 上传完成但未拿到URL的提示 --> <div *ngIf="uploadCompleted && !(downloadURL | async)" class="alert alert-warning mt-3" role="alert"> 上传完成,正在获取下载链接... </div> <!-- 下载链接展示 --> <div *ngIf="downloadURL | async; let downloadSrc" class="alert alert-info mt-3" role="alert"> File uploaded: <a [href]="downloadSrc">{{downloadSrc}}</a> </div> </div> </div>
这样修改后,你就不用手动点击按钮等待上传完成了——代码会自动在上传结束后安全获取下载URL,同时还能给用户清晰的状态反馈。
内容的提问来源于stack exchange,提问作者Tagz
相关产品推荐
相关产品推荐

