Reputation: 345
I can't understand the process of getting the download URl, Can someone please break it down to me nicely? So I have this upload component here:
import { Component, OnInit } from '@angular/core';
import { AngularFireStorage, AngularFireUploadTask } from
'angularfire2/storage';
import { AngularFirestore } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import { tap, filter, switchMap } from 'rxjs/operators';
import { storage } from 'firebase/storage';
@Component({
selector: 'file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.scss']
})
export class FileUploadComponent {
// Main task
task: AngularFireUploadTask;
// Progress monitoring
percentage: Observable<number>;
snapshot: Observable<any>;
// Download URL
downloadURL: Observable<string>;
// State for dropzone CSS toggling
isHovering: boolean;
constructor(private storage: AngularFireStorage, private db: AngularFirestore) { }
toggleHover(event: boolean) {
this.isHovering = event;
}
startUpload(event: FileList) {
// The File object
const file = event.item(0)
// Client-side validation example
if (file.type.split('/')[0] !== 'image') {
console.error('unsupported file type :( ')
return;
}
// The storage path
const path = `test/${new Date().getTime()}_${file.name}`;
// Totally optional metadata
const customMetadata = { app: 'My AngularFire-powered PWA!' };
// The main task
this.task = this.storage.upload(path, file, { customMetadata })
// Progress monitoring
this.percentage = this.task.percentageChanges();
this.snapshot = this.task.snapshotChanges().pipe(
tap(snap => {
console.log(snap)
if (snap.bytesTransferred === snap.totalBytes) {
// Update firestore on completion
this.db.collection('photos').add( { path, size: snap.totalBytes })
}
})
)
// The file's download URL
this.downloadURL = this.task.downloadURL();
console.log(this.downloadURL)
const ref = this.storage.ref(path);
this.task = ref.put(file, {customMetadata});
this.downloadURL = this.task.snapshotChanges().pipe(
filter(snap => snap.state === storage.TaskState.SUCCESS),
switchMap(() => ref.getDownloadURL())
)
console.log(this.downloadURL);
}
// Determines if the upload task is active
isActive(snapshot) {
return snapshot.state === 'running' && snapshot.bytesTransferred < snapshot.totalBytes
}}
I try to console the supposed way of getting the download URL but it's empty, i've seen some other ways to get it done but can't seem to get it right. Download URL is always null even with snapshot.downloadURL. Following is the package.json:
{
"name": "storage-app",
"version": "0.0.0",
"license": "MIT",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "^6.0.3",
"@angular/common": "^6.0.3",
"@angular/compiler": "^6.0.3",
"@angular/core": "^6.0.3",
"@angular/forms": "^6.0.3",
"@angular/http": "^6.0.3",
"@angular/platform-browser": "^6.0.3",
"@angular/platform-browser-dynamic": "^6.0.3",
"@angular/platform-server": "^6.0.3",
"@angular/router": "^6.0.3",
"angularfire2": "5.0.0-rc.6",
"core-js": "^2.5.4",
"firebase": "4.12.1",
"rxjs": "^6.0.0",
"rxjs-compat": "^6.2.2",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@angular/cli": "^6.0.8",
"@angular/compiler-cli": "^6.0.3",
"@angular/language-service": "^6.0.3",
"@types/jasmine": "~2.5.53",
"@types/jasminewd2": "~2.0.2",
"@types/node": "~6.0.60",
"codelyzer": "^4.0.1",
"jasmine-core": "~2.6.2",
"jasmine-spec-reporter": "~4.1.0",
"karma": "~1.7.0",
"karma-chrome-launcher": "~2.1.1",
"karma-cli": "~1.0.1",
"karma-coverage-istanbul-reporter": "^1.2.1",
"karma-jasmine": "~1.1.0",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.1.2",
"ts-node": "~3.2.0",
"tslint": "~5.7.0",
"typescript": "~2.7.2",
"@angular-devkit/build-angular": "~0.6.8"
}
}
Thanks in advance
Upvotes: 2
Views: 3942
Reputation: 1818
Angularfire provides this super convenient pipe, getDownloadURL:
<img [src]="'users/davideast.jpg' | getDownloadURL" />
Official docs.
The end.
Upvotes: 0
Reputation: 39482
Here's a simple example to help you understand how(taken from AngularFire2 GitHub):
uploadPercent: Observable < number > ;
downloadURL: Observable < string > ;
constructor(
private storage: AngularFireStorage
) {
}
uploadFile(event) {
const file = event.target.files[0];
const filePath = 'files';
const fileRef = this.storage.ref(filePath);
const task = this.storage.upload(filePath, file);
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
task.snapshotChanges().pipe(
finalize(() => this.downloadURL = fileRef.getDownloadURL())
)
.subscribe()
}
And here's the template for this:
<input type="file" (change)="uploadFile($event)" />
<div>{{ uploadPercent | async }}</div>
<a [href]="downloadURL | async">{{ downloadURL | async }}</a>
Here's what's happening:
We're acting upon the change
event of File Input. Once that is done, we'll get the file to upload. We're then creating a file reference on our Firebase storage by calling ref
and passing it the path to our file. This will be helpful later in retrieveing the File Download URL.
After that, we're creating an AngularFireUplaodTask by calling upload on storage
and passing it the filepath and the file to be uploaded.
On this task, we can check for the file upload percentage by calling percentageChanges
on the upload task. This is again an Observable and thus we're listening for and printing changes on the DOM by using the async
pipe.
finalize
will get triggered when the upload task is done. And that's when we'll be able to get the download url by calling getDownloadURL
on the fileRef
that we created earlier.
You can have a look at this StackBlitz for more info.
Upvotes: 0
Reputation: 70466
You can retrieve the download url from the storage ref:
loading = false;
uploadFile(event) {
this.loading = true;
const file = event.target.files[0];
// give it a random file name
const path = Math.random().toString(36).substring(7);
const storageRef = this.storage.ref(path);
const task = this.storage.upload(path, file);
return from(task).pipe(
switchMap(() => storageRef.getDownloadURL()),
tap(url => {
// use url here, e.g. assign it to a model
}),
mergeMap(() => {
// e.g. make api call, e.g. save the model
}),
finalize(() => this.loading = false)
).subscribe(() => {
// success
}, error => {
// failure
});
}
I am using angularfire 5.0.0-rc.11
Upvotes: 2