Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 - Getting download URL for Firebase Storage file after uploading

What I'm trying to accomplish here is a simple idea.

  1. Upload file to Firebase Storage

  2. Grab the link to the file and insert it in the form.

Problem is, I can't get the download URL.

When I upload something, it does upload, but I get this error message:

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" }

And this is the code to upload on 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();
}

And on component.html:

<input type="file" (change)="upload($event)" accept=".png,.jpg" />

How can I grab the downloadURL after the file is uploaded?

like image 476
Rosenberg Avatar asked Jul 19 '18 19:07

Rosenberg


2 Answers

You should add a finalize() to the pipe, something like:

this.task.snapshotChanges().pipe(
  finalize(() => {
    this.downloadURL = this.ref.getDownloadURL(); // <-- Here the downloadURL is available.
  })
).subscribe();

In the finalize() step, the downloadURL is available, so u can grab him from the ref asynchronously. --UPDATE
You said you are using Angular 6, so I assume you are using the last version of firebase.
They change getDownloadURL() to Observable from Task, So to get the actual URL you just have to subscribe.

this.task.snapshotChanges().pipe(
  finalize(() => {
    this.ref.getDownloadURL().subscribe(url => {
      console.log(url); // <-- do what ever you want with the url..
    });
  })
).subscribe();
like image 117
dAxx_ Avatar answered Oct 19 '22 03:10

dAxx_


ref.getDownloadURL() has to be called after task.snapshotChanges() completes.

Option 1: You can use concat and defer the execution of 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));

Option 2: switchMap to ref.getDownloadURL() after task.snapshotChanges() completes.

this.task.snapshotChanges().pipe(
  last(),  // emit the last element after task.snapshotChanges() completed
  switchMap(() => this.ref.getDownloadURL())
).subscribe(url => console.log(url))
like image 31
frido Avatar answered Oct 19 '22 04:10

frido