Angular 6 - 上传后获取 Firebase 存储文件的下载 URL
Posted
技术标签:
【中文标题】Angular 6 - 上传后获取 Firebase 存储文件的下载 URL【英文标题】:Angular 6 - Getting download URL for Firebase Storage file after uploading 【发布时间】:2018-12-28 00:52:01 【问题描述】:我在这里想要完成的是一个简单的想法。
将文件上传到 Firebase 存储
获取文件的链接并将其插入表单中。
问题是,我无法获取下载地址。
当我上传某些内容时,它确实会上传,但我收到以下错误消息:
Object code_: "storage/object-not-found", message_: "Firebase Storage: Object 'rnmgm3vvpz' does not exist.", serverResponse_: "\n \"error\": \n \"code\": 404,\n \"message\": \"Not Found. Could not get object\"\n \n", name_: "FirebaseError"
这是要上传到component.ts的代码:
upload(event)
const id = Math.random().toString(36).substring(2);
this.ref = this.afStorage.ref(id);
this.task = this.ref.put(event.target.files[0]);
this.uploadState = this.task.snapshotChanges().pipe(map(s => s.state));
this.uploadProgress = this.task.percentageChanges();
this.downloadURL = this.ref.getDownloadURL();
在component.html上:
<input type="file" (change)="upload($event)" accept=".png,.jpg" />
文件上传后如何获取downloadURL?
【问题讨论】:
试试这个答案在这个时间点是如何工作的https://***.com/a/57267424/11127383 找不到对象,因为应该在文件完成加载后进行 downloadURL 调用。如@dAxx_所述,将其从uploadEvent 函数中删除并添加到finalize 函数中 【参考方案1】:您应该在管道中添加一个 finalize(),例如:
this.task.snapshotChanges().pipe(
finalize(() =>
this.downloadURL = this.ref.getDownloadURL(); // <-- Here the downloadURL is available.
)
).subscribe();
在 finalize() 步骤中,downloadURL 可用,因此您可以从 ref 中异步获取他。 --更新 您说您使用的是 Angular 6,所以我假设您使用的是最新版本的 firebase。 他们将 getDownloadURL() 从 Task 更改为 Observable,因此要获取实际 URL,您只需订阅即可。
this.task.snapshotChanges().pipe(
finalize(() =>
this.ref.getDownloadURL().subscribe(url =>
console.log(url); // <-- do what ever you want with the url..
);
)
).subscribe();
【讨论】:
StorageReference.getDownloadUrl()
返回 Task
而不是实际的 URL。您可能想要更新您的答案,以展示如何向任务添加完成侦听器并从中获取实际 URL。
@FrankvanPuffelen 正是我得到的。这是一个很好的答案,但它没有给我下载 URL。
@Rosenberg,如果您使用的是最新的 firebase,getDownloadURL() 不是任务,而是 Observable。我编辑我的帖子以获得答案。祝你好运..
啊...您正在使用 AngularFire。它确实是一个可观察的,它也巧妙地摆脱/封装了异步行为。【参考方案2】:
ref.getDownloadURL()
必须在 task.snapshotChanges()
完成后调用。
选项1:可以使用concat
和defer
执行ref.getDownloadURL()
concat(
this.task.snapshotChanges().pipe(ignoreElements()) // ignore snapshot changes
defer(() => this.ref.getDownloadURL()) // execute getDownloadURL when snapshot changes completed
).subscribe(url => console.log(url));
选项 2: 在task.snapshotChanges()
完成后,switchMap
到 ref.getDownloadURL()
。
this.task.snapshotChanges().pipe(
last(), // emit the last element after task.snapshotChanges() completed
switchMap(() => this.ref.getDownloadURL())
).subscribe(url => console.log(url))
【讨论】:
【参考方案3】:this.angularFireStorage.upload("path_name", file).then(rst =>
rst.ref.getDownloadURL().then(url =>
console.log(url);
)
)
这就是答案。不想打两次电话。我的包版本是
"@angular/fire": "^5.1.2", “火力基地”:“^5.9.1”
【讨论】:
【参考方案4】:@dAxx_ 答案的开头是正确的,但是嵌套订阅是非常糟糕的做法。
查看这个 *** 答案Is it good way to call subscribe inside subscribe?
现在,AngularFire docs 已经很清楚了,除了可能在以下示例中使用 getDownloadURL 管道
@Component(
selector: 'app-root',
template: `<img [src]="'users/davideast.jpg' | getDownloadURL" />`
)
export class AppComponent
他们可能会提到您需要在相关模块中进行以下导入
import GetDownloadURLPipeModule from '@angular/fire/compat/storage';
...
imports: [
GetDownloadURLPipeModule
],...
但是,如果您可能不需要下载 URL,那么简单的答案。
我不确定其背后的原因是什么,但 Firebase 团队已经为我们提供了足够的方式来显示上传的图片,而无需关心下载 URL 字符串。
首先,getDownloadURL 是一个 Observable,因此您可以像这样显示您的图像
...
finalize(() =>
this.downloadURL = this.ref.getDownloadURL()
...
<img *ngIf="downloadURL | async as imgUrl" [src]="imgUrl" >
或者,您可以使用我上面提到的第一个解决方案,使用文件路径和 getDownloadURL 管道
最后,您可以使用 Angular Fire 文档中的以下示例
@Component(
selector: 'app-root',
template: `<img [src]="profileUrl | async" />`
)
export class AppComponent
profileUrl: Observable<string | null>;
constructor(private storage: AngularFireStorage)
const ref = this.storage.ref('users/davideast.jpg');
this.profileUrl = ref.getDownloadURL();
在这种情况下,您只需要关心文件路径,例如,如果您需要在数据库中保存对上传图像的引用。
【讨论】:
【参考方案5】:试试这个,对我有用
task.snapshotChanges()
.pipe(
finalize(() =>
this.downloadURL = fileRef.getDownloadURL();
this.downloadURL.subscribe(downloadURLResponse =>
console.log('downloadURL', downloadURLResponse);
);
),
)
.subscribe();
【讨论】:
【参考方案6】:这是一个包含所有导入的完整方法。
import AngularFireStorage, AngularFireStorageReference, AngularFireUploadTask from '@angular/fire/storage';
import finalize from 'rxjs/operators';
constructor(private afStorage:AngularFireStorage)
yourfile:File;
onsubmit()
const id = Math.random().toString(36).substring(2);
const fileRef:AngularFireStorageReference=this.afStorage.ref("YourDir").child(id);
const task: AngularFireUploadTask =fileRef.put(this.yourfile);
task.snapshotChanges().pipe(
finalize(() =>
fileRef.getDownloadURL().subscribe(downloadURL =>
this.profileurl=downloadURL;
console.log(downloadURL);
);
)
).subscribe();
【讨论】:
以上是关于Angular 6 - 上传后获取 Firebase 存储文件的下载 URL的主要内容,如果未能解决你的问题,请参考以下文章
启动后为 Angular 6 项目获取“错误 TS1005,TS1109”