Build a file upload dropzone in Angular using the brand new storage module in AngularFire2. Learn how to easily send files from an Angular PWA to Firebase Storage.  https://angularfirebase.com/lessons/firebase-storage-with-angularfire-dropzone-file-uploader/

- AngularFire2 Storage: https://github.com/angular/angularfire2/tree/master/docs/storage
- Firebase Storage: https://firebase.google.com/docs/storage/
- Angular: https://angular.io/
2024-02-04T07:48:11.579Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
2f2776b7-75a2-46a8-97df-8ebf28f7bcbe
3630d3d6d0a734d902e31d1bc74be483ab7ae1837c00948370b0fc9b49db347a
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before.
In this episode, I'm going to take you through the new features in the AngularFire 2 storage module.
Up then we'll use it to build a drop zone file uploader from scratch.
In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload.
There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com.
Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works.
When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket.
You can then monitor the upload progress as an observable.
The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback.
When the process is complete, it will give you back the download URL that you can show in your front end UI.
Now let's go ahead and build this thing.
We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase.
Then inside of your Angular environment, add your Firebase project config.
And lastly, we'll go into the app module and initialize our AngularFire app.
I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video.
Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app.
We want the user to drag and drop a file, which is a perfect use case for an Angular directive.
We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity.
We can create custom events in Angular by using a combination of host listener, output and event emitter.
The first thing we do is create our custom events, which we do with the output decorator.
The first event is called dropped and it is fired when the user drops their files onto the drop zone.
The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase.
I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes.
From there, we can use host listener to listen to the drop event from the browser.
And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab.
The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter.
We'll also set the hover event to false.
That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs.
Then we can emit false on the drag leave event.
And we'll also wanna prevent default on these events as well.
That gives us a bare minimum drop zone.
Now let's put it to use in a file upload component.
The goal here is to give you a pretty extensive tour the new functionality in the storage module.
The first thing we'll do is import AngularFire storage and the AngularFire upload task.
From there, we're going to declare a few variables.
The main part of AngularFire storage is the task.
It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload.
One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar.
But you can get even more data than that by observing the actual snapshot.
When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable.
The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes.
The next step is to inject AngularFire storage into the constructor.
Then what I really wanna focus on is this start upload method which will kick off the entire upload process.
This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier.
So when the drop event fires, it's going to start the upload.
We can get the first file from the list by calling event item 0.
A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once.
The next thing you might wanna do is provide some client side validation.
So in this case, we only want the user to be able to upload image files.
We can look at the MIME type on the file that was selected.
And if it's not an image, we'll just go ahead and console error and return from this function.
And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules.
To do that, we look at the incoming request and make sure that the content type matches image.
Now that we secured our upload, we need to tell Firebase where to actually save it.
Storage doesn't generate a unique ID like the Firestore database does.
So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name.
The easiest method is just to use a JavaScript date with git time and append it to the file name.
That's going to make file name collisions extremely unlikely.
You can also save your own custom metadata on the image itself.
There's probably a ton of different use cases.
But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image.
Let's say it was uploaded from my AngularFire powered progressive web app.
At this point, we have everything we need to define the actual upload task.
To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata.
And the metadata is completely optional by the way.
When we call upload, it's going to immediately start the upload process.
There's no need to call subscribe on it like you would with an observable.
It works by giving us observables that we can listen to to monitor the actual upload progress.
We get the observables by calling percentage changes and snapshot changes.
Up.
And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete.
Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states.
Every snapshot that gets emitted has a state which might be running or paused.
And we can also look at the bytes transferred and compare them to the total bytes in the file.
The data contained in the snapshot can be very useful for customizing the behavior of your front end UI.
Now let's jump over to the component CSS file.
I'm not really going to talk about the CSS, but I do wanna give you one helpful tip.
The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation.
In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar.
Now let's jump over to the HTML and put everything together.
1st, we'll set up a div and add our custom drop zone directive to it.
That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div.
That emits a file list, which will pass on to our start upload method to immediately start the upload process.
In addition to drag and drop, we also wanna give it just plain file upload button.
This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device.
All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method.
That's all it takes to build a drop zone, but we also wanna show a progress bar.
To do that, we're going to use the percentage observable that we set in the component type script.
We can unwrap it with the async pipe and then set it as a template variable called percent.
It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar.
That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well.
The snapshot contains information about the bytes transferred and the total bytes in the file.
That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera.
The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same.
The next thing we can do is unwrap the download URL.
We can give the user a URL to download the file directly.
But since we're dealing with images here, we can also set that URL as the source of an HTML image.
Up.
Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task.
Doing that is incredibly simple.
All we have to do is set up a button and bind the task pause method to the click event.
Then we only want the user to be able to fire this if the upload is actually active at the time.
So we can use that is active helper that we already defined and pass it the snapshot.
We also have a cancel method on the task which we can set up in the exact same way.
Then if the download is paused, we wanna give the user a way to resume it.
So to do that, we call task resume.
And this button should be disabled unless the snapshot state equals paused.
A.
And just like that, you now have your own AngularFire drop zone.
But we're not quite done yet because I did promise you one more advanced thing with Firestore.
There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database.
We can do this with just a few lines of code.
First, we'll bring in Firestore and the tap operator from RxJS.
Then we'll inject AngularFirestore in the constructor.
Because we already have an observable of the snapshot is for the upload.
We can pipe in the tap operator to make a call to our database once the upload is complete.
What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file.
Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file.
The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file.
Now let's jump over the Firebase console and make sure everything works.
1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom.
Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location.
In other words, you have successfully connected your persistent app data with your stored files.
I'm going to wrap things up there.
If this video helped you, please like and subscribe.
And you can look forward to a whole bunch more videos in the near future involving AngularFire storage.
Thanks for watching, and I'll see you soon.

Speaker 0: Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before. In this episode, I'm going to take you through the new features in the AngularFire 2 storage module. Up then we'll use it to build a drop zone file uploader from scratch. In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload. There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com.

Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works. When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket. You can then monitor the upload progress as an observable. The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback. When the process is complete, it will give you back the download URL that you can show in your front end UI.

Now let's go ahead and build this thing. We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase. Then inside of your Angular environment, add your Firebase project config. And lastly, we'll go into the app module and initialize our AngularFire app. I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video.

Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app. We want the user to drag and drop a file, which is a perfect use case for an Angular directive. We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity. We can create custom events in Angular by using a combination of host listener, output and event emitter. The first thing we do is create our custom events, which we do with the output decorator.

The first event is called dropped and it is fired when the user drops their files onto the drop zone. The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase. I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes. From there, we can use host listener to listen to the drop event from the browser. And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab.

The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter. We'll also set the hover event to false. That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs. Then we can emit false on the drag leave event. And we'll also wanna prevent default on these events as well.

That gives us a bare minimum drop zone. Now let's put it to use in a file upload component. The goal here is to give you a pretty extensive tour the new functionality in the storage module. The first thing we'll do is import AngularFire storage and the AngularFire upload task. From there, we're going to declare a few variables.

The main part of AngularFire storage is the task. It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload. One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar. But you can get even more data than that by observing the actual snapshot. When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable.

The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes. The next step is to inject AngularFire storage into the constructor. Then what I really wanna focus on is this start upload method which will kick off the entire upload process. This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier. So when the drop event fires, it's going to start the upload.

We can get the first file from the list by calling event item 0. A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once. The next thing you might wanna do is provide some client side validation. So in this case, we only want the user to be able to upload image files. We can look at the MIME type on the file that was selected.

And if it's not an image, we'll just go ahead and console error and return from this function. And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules. To do that, we look at the incoming request and make sure that the content type matches image. Now that we secured our upload, we need to tell Firebase where to actually save it. Storage doesn't generate a unique ID like the Firestore database does.

So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name. The easiest method is just to use a JavaScript date with git time and append it to the file name. That's going to make file name collisions extremely unlikely. You can also save your own custom metadata on the image itself. There's probably a ton of different use cases.

But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image. Let's say it was uploaded from my AngularFire powered progressive web app. At this point, we have everything we need to define the actual upload task. To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata. And the metadata is completely optional by the way.

When we call upload, it's going to immediately start the upload process. There's no need to call subscribe on it like you would with an observable. It works by giving us observables that we can listen to to monitor the actual upload progress. We get the observables by calling percentage changes and snapshot changes. Up.

And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete. Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states. Every snapshot that gets emitted has a state which might be running or paused. And we can also look at the bytes transferred and compare them to the total bytes in the file. The data contained in the snapshot can be very useful for customizing the behavior of your front end UI.

Now let's jump over to the component CSS file. I'm not really going to talk about the CSS, but I do wanna give you one helpful tip. The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation. In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar. Now let's jump over to the HTML and put everything together.

1st, we'll set up a div and add our custom drop zone directive to it. That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div. That emits a file list, which will pass on to our start upload method to immediately start the upload process. In addition to drag and drop, we also wanna give it just plain file upload button. This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device.

All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method. That's all it takes to build a drop zone, but we also wanna show a progress bar. To do that, we're going to use the percentage observable that we set in the component type script. We can unwrap it with the async pipe and then set it as a template variable called percent. It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar.

That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well. The snapshot contains information about the bytes transferred and the total bytes in the file. That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera. The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same. The next thing we can do is unwrap the download URL.

We can give the user a URL to download the file directly. But since we're dealing with images here, we can also set that URL as the source of an HTML image. Up. Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task. Doing that is incredibly simple.

All we have to do is set up a button and bind the task pause method to the click event. Then we only want the user to be able to fire this if the upload is actually active at the time. So we can use that is active helper that we already defined and pass it the snapshot. We also have a cancel method on the task which we can set up in the exact same way. Then if the download is paused, we wanna give the user a way to resume it.

So to do that, we call task resume. And this button should be disabled unless the snapshot state equals paused. A. And just like that, you now have your own AngularFire drop zone. But we're not quite done yet because I did promise you one more advanced thing with Firestore.

There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database. We can do this with just a few lines of code. First, we'll bring in Firestore and the tap operator from RxJS. Then we'll inject AngularFirestore in the constructor. Because we already have an observable of the snapshot is for the upload.

We can pipe in the tap operator to make a call to our database once the upload is complete. What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file. Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file. The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file. Now let's jump over the Firebase console and make sure everything works.

1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom. Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location. In other words, you have successfully connected your persistent app data with your stored files. I'm going to wrap things up there. If this video helped you, please like and subscribe.

And you can look forward to a whole bunch more videos in the near future involving AngularFire storage. Thanks for watching, and I'll see you soon.
Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before. In this episode, I'm going to take you through the new features in the AngularFire 2 storage module. Up then we'll use it to build a drop zone file uploader from scratch. In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload. There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com. Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works. When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket.
You can then monitor the upload progress as an observable. The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback. When the process is complete, it will give you back the download URL that you can show in your front end UI.
streaming
multimedia
Now let's go ahead and build this thing. We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase. Then inside of your Angular environment, add your Firebase project config. And lastly, we'll go into the app module and initialize our AngularFire app. I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video. Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app. We want the user to drag and drop a file, which is a perfect use case for an Angular directive. We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity. We can create custom events in Angular by using a combination of host listener, output and event emitter. The first thing we do is create our custom events, which we do with the output decorator. The first event is called dropped and it is fired when the user drops their files onto the drop zone. The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase. I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes.
From there, we can use host listener to listen to the drop event from the browser. And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab. The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter.
streaming
We'll also set the hover event to false. That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs. Then we can emit false on the drag leave event. And we'll also wanna prevent default on these events as well. That gives us a bare minimum drop zone. Now let's put it to use in a file upload component. The goal here is to give you a pretty extensive tour the new functionality in the storage module. The first thing we'll do is import AngularFire storage and the AngularFire upload task. From there, we're going to declare a few variables. The main part of AngularFire storage is the task.
It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload. One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar. But you can get even more data than that by observing the actual snapshot. When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable. The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes.
data
streaming
visualization
The next step is to inject AngularFire storage into the constructor. Then what I really wanna focus on is this start upload method which will kick off the entire upload process. This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier. So when the drop event fires, it's going to start the upload. We can get the first file from the list by calling event item 0. A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once. The next thing you might wanna do is provide some client side validation.
So in this case, we only want the user to be able to upload image files. We can look at the MIME type on the file that was selected. And if it's not an image, we'll just go ahead and console error and return from this function. And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules.
streaming
To do that, we look at the incoming request and make sure that the content type matches image. Now that we secured our upload, we need to tell Firebase where to actually save it. Storage doesn't generate a unique ID like the Firestore database does. So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name. The easiest method is just to use a JavaScript date with git time and append it to the file name. That's going to make file name collisions extremely unlikely.
You can also save your own custom metadata on the image itself. There's probably a ton of different use cases. But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image. Let's say it was uploaded from my AngularFire powered progressive web app.
animation
photography
multimedia
At this point, we have everything we need to define the actual upload task. To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata. And the metadata is completely optional by the way. When we call upload, it's going to immediately start the upload process. There's no need to call subscribe on it like you would with an observable.
It works by giving us observables that we can listen to to monitor the actual upload progress. We get the observables by calling percentage changes and snapshot changes. Up. And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete.
streaming
Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states. Every snapshot that gets emitted has a state which might be running or paused. And we can also look at the bytes transferred and compare them to the total bytes in the file. The data contained in the snapshot can be very useful for customizing the behavior of your front end UI. Now let's jump over to the component CSS file.
I'm not really going to talk about the CSS, but I do wanna give you one helpful tip. The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation. In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar. Now let's jump over to the HTML and put everything together. 1st, we'll set up a div and add our custom drop zone directive to it. That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div.
animation
That emits a file list, which will pass on to our start upload method to immediately start the upload process. In addition to drag and drop, we also wanna give it just plain file upload button.
This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device. All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method.
photography
multimedia
That's all it takes to build a drop zone, but we also wanna show a progress bar. To do that, we're going to use the percentage observable that we set in the component type script. We can unwrap it with the async pipe and then set it as a template variable called percent. It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar. That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well. The snapshot contains information about the bytes transferred and the total bytes in the file. That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera. The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same. The next thing we can do is unwrap the download URL. We can give the user a URL to download the file directly. But since we're dealing with images here, we can also set that URL as the source of an HTML image. Up. Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task. Doing that is incredibly simple. All we have to do is set up a button and bind the task pause method to the click event. Then we only want the user to be able to fire this if the upload is actually active at the time. So we can use that is active helper that we already defined and pass it the snapshot. We also have a cancel method on the task which we can set up in the exact same way. Then if the download is paused, we wanna give the user a way to resume it. So to do that, we call task resume. And this button should be disabled unless the snapshot state equals paused. A. And just like that, you now have your own AngularFire drop zone. But we're not quite done yet because I did promise you one more advanced thing with Firestore. There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database. We can do this with just a few lines of code. First, we'll bring in Firestore and the tap operator from RxJS. Then we'll inject AngularFirestore in the constructor. Because we already have an observable of the snapshot is for the upload. We can pipe in the tap operator to make a call to our database once the upload is complete. What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file. Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file. The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file. Now let's jump over the Firebase console and make sure everything works. 1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom.
Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location. In other words, you have successfully connected your persistent app data with your stored files. I'm going to wrap things up there. If this video helped you, please like and subscribe. And you can look forward to a whole bunch more videos in the near future involving AngularFire storage. Thanks for watching, and I'll see you soon.
streaming
youtube
multimedia
databases
data management
Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before. In this episode, I'm going to take you through the new features in the AngularFire 2 storage module. Up then we'll use it to build a drop zone file uploader from scratch. In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload. There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com. Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works. When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket. You can then monitor the upload progress as an observable. The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback. When the process is complete, it will give you back the download URL that you can show in your front end UI. Now let's go ahead and build this thing. We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase. Then inside of your Angular environment, add your Firebase project config. And lastly, we'll go into the app module and initialize our AngularFire app. I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video. Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app. We want the user to drag and drop a file, which is a perfect use case for an Angular directive. We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity. We can create custom events in Angular by using a combination of host listener, output and event emitter. The first thing we do is create our custom events, which we do with the output decorator. The first event is called dropped and it is fired when the user drops their files onto the drop zone. The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase. I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes. From there, we can use host listener to listen to the drop event from the browser. And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab. The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter. We'll also set the hover event to false. That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs. Then we can emit false on the drag leave event. And we'll also wanna prevent default on these events as well. That gives us a bare minimum drop zone. Now let's put it to use in a file upload component. The goal here is to give you a pretty extensive tour the new functionality in the storage module. The first thing we'll do is import AngularFire storage and the AngularFire upload task. From there, we're going to declare a few variables. The main part of AngularFire storage is the task. It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload. One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar. But you can get even more data than that by observing the actual snapshot. When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable. The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes. The next step is to inject AngularFire storage into the constructor. Then what I really wanna focus on is this start upload method which will kick off the entire upload process. This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier. So when the drop event fires, it's going to start the upload. We can get the first file from the list by calling event item 0. A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once. The next thing you might wanna do is provide some client side validation. So in this case, we only want the user to be able to upload image files. We can look at the MIME type on the file that was selected. And if it's not an image, we'll just go ahead and console error and return from this function. And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules. To do that, we look at the incoming request and make sure that the content type matches image. Now that we secured our upload, we need to tell Firebase where to actually save it. Storage doesn't generate a unique ID like the Firestore database does. So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name. The easiest method is just to use a JavaScript date with git time and append it to the file name. That's going to make file name collisions extremely unlikely. You can also save your own custom metadata on the image itself. There's probably a ton of different use cases. But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image. Let's say it was uploaded from my AngularFire powered progressive web app. At this point, we have everything we need to define the actual upload task. To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata. And the metadata is completely optional by the way. When we call upload, it's going to immediately start the upload process. There's no need to call subscribe on it like you would with an observable. It works by giving us observables that we can listen to to monitor the actual upload progress. We get the observables by calling percentage changes and snapshot changes. Up. And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete. Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states. Every snapshot that gets emitted has a state which might be running or paused. And we can also look at the bytes transferred and compare them to the total bytes in the file. The data contained in the snapshot can be very useful for customizing the behavior of your front end UI. Now let's jump over to the component CSS file. I'm not really going to talk about the CSS, but I do wanna give you one helpful tip. The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation. In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar. Now let's jump over to the HTML and put everything together. 1st, we'll set up a div and add our custom drop zone directive to it. That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div. That emits a file list, which will pass on to our start upload method to immediately start the upload process. In addition to drag and drop, we also wanna give it just plain file upload button. This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device. All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method. That's all it takes to build a drop zone, but we also wanna show a progress bar. To do that, we're going to use the percentage observable that we set in the component type script. We can unwrap it with the async pipe and then set it as a template variable called percent. It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar. That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well. The snapshot contains information about the bytes transferred and the total bytes in the file. That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera. The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same. The next thing we can do is unwrap the download URL. We can give the user a URL to download the file directly. But since we're dealing with images here, we can also set that URL as the source of an HTML image. Up. Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task. Doing that is incredibly simple. All we have to do is set up a button and bind the task pause method to the click event. Then we only want the user to be able to fire this if the upload is actually active at the time. So we can use that is active helper that we already defined and pass it the snapshot. We also have a cancel method on the task which we can set up in the exact same way. Then if the download is paused, we wanna give the user a way to resume it. So to do that, we call task resume. And this button should be disabled unless the snapshot state equals paused. A. And just like that, you now have your own AngularFire drop zone. But we're not quite done yet because I did promise you one more advanced thing with Firestore. There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database. We can do this with just a few lines of code. First, we'll bring in Firestore and the tap operator from RxJS. Then we'll inject AngularFirestore in the constructor. Because we already have an observable of the snapshot is for the upload. We can pipe in the tap operator to make a call to our database once the upload is complete. What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file. Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file. The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file. Now let's jump over the Firebase console and make sure everything works. 1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom. Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location. In other words, you have successfully connected your persistent app data with your stored files. I'm going to wrap things up there. If this video helped you, please like and subscribe. And you can look forward to a whole bunch more videos in the near future involving AngularFire storage. Thanks for watching, and I'll see you soon.
Firebase
firebase
Storage
storage
is
is
now
now
officially
officially
supported
supported
by
by
AngularFire
angularfire
2,
2
which
which
means
means
uploading
uploading
files
files
from
from
an
an
Angular
angular
application
application
is
is
easier
easier
than
than
ever
ever
before.
before
In
in
this
this
episode,
episode
I'm
i'm
going
going
to
to
take
take
you
you
through
through
the
the
new
new
features
features
in
in
the
the
AngularFire
angularfire
2
2
storage
storage
module.
module
Up
up
then
then
we'll
we'll
use
use
it
it
to
to
build
build
a
a
drop
drop
zone
zone
file
file
uploader
uploader
from
from
scratch.
scratch
In
in
addition
addition
to
to
uploading
uploading
files
files
to
to
Firebase
firebase
Storage,
storage
it
it
can
can
also
also
control
control
the
the
entire
entire
upload
upload
process
process
by
by
pausing,
pausing
canceling,
canceling
or
or
resuming
resuming
an
an
upload.
upload
There's
there's
a
a
whole
whole
bunch
bunch
of
of
other
other
cool
cool
stuff
stuff
I
i
wanna
wanna
show
show
you,
you
but
but
first
first
make
make
sure
sure
to
to
like
like
and
and
subscribe
subscribe
and
and
grab
grab
the
the
source
source
code
code
from
from
angularfirebase.com.
angularfirebase.com
Before
before
we
we
jump
jump
into
into
the
the
code,
code
I
i
wanna
wanna
give
give
you
you
a
a
few
few
more
more
details
details
about
about
how
how
the
the
AngularFire
angularfire
2
2
storage
storage
module
module
works.
works
When
when
we
we
drag
drag
and
and
drop
drop
a
a
file,
file
it's
it's
going
going
to
to
start
start
an
an
AngularFire
angularfire
upload
upload
task,
task
which
which
will
will
immediately
immediately
start
start
uploading
uploading
the
the
file
file
to
to
your
your
Firebase
firebase
storage
storage
bucket.
bucket
You
you
can
can
then
then
monitor
monitor
the
the
upload
upload
progress
progress
as
as
an
an
observable.
observable
The
the
snapshot
snapshot
is
is
emitted
emitted
several
several
times
times
per
per
second,
second
so
so
you
you
can
can
do
do
things
things
like
like
update
update
your
your
progress
progress
or
or
or
or
just
just
provide
provide
the
the
user
user
with
with
some
some
helpful
helpful
feedback.
feedback
When
when
the
the
process
process
is
is
complete,
complete
it
it
will
will
give
give
you
you
back
back
the
the
download
download
URL
url
that
that
you
you
can
can
show
show
in
in
your
your
front
front
end
end
UI.
ui
Now
now
let's
let's
go
go
ahead
ahead
and
and
build
build
this
this
thing.
thing
We'll
we'll
start
start
with
with
a
a
brand
brand
new
new
Angular
angular
5
5
app,
app
and
and
then
then
inside
inside
that
that
project,
project
install
install
AngularFire
angularfire
2
2
and
and
Firebase.
firebase
Then
then
inside
inside
of
of
your
your
Angular
angular
environment,
environment
add
add
your
your
Firebase
firebase
project
project
config.
config
And
and
lastly,
lastly
we'll
we'll
go
go
into
into
the
the
app
app
module
module
and
and
initialize
initialize
our
our
AngularFire
angularfire
app.
app
I'm
i'm
bringing
bringing
in
in
both
both
the
the
AngularFire
angularfire
storage
storage
module
module
and
and
the
the
Firestore
firestore
database
database
for
for
some
some
advanced
advanced
stuff
stuff
I'll
i'll
show
show
you
you
towards
towards
the
the
end
end
of
of
the
the
video.
video
Now
now
that
that
we
we
have
have
AngularFire
angularfire
2
2
set
set
up,
up
we
we
need
need
a
a
way
way
to
to
retrieve
retrieve
a
a
file
file
from
from
the
the
user's
user's
device
device
into
into
our
our
Angular
angular
app.
app
We
we
want
want
the
the
user
user
to
to
drag
drag
and
and
drop
drop
a
a
file,
file
which
which
is
is
a
a
perfect
perfect
use
use
case
case
for
for
an
an
Angular
angular
directive.
directive
We
we
want
want
to
to
use
use
this
this
directive
directive
on
on
an
an
HTML
html
element
element
and
and
have
have
it
it
emit
emit
custom
custom
events
events
based
based
on
on
certain
certain
drag
drag
and
and
drop
drop
activity.
activity
We
we
can
can
create
create
custom
custom
events
events
in
in
Angular
angular
by
by
using
using
a
a
combination
combination
of
of
host
host
listener,
listener
output
output
and
and
event
event
emitter.
emitter
The
the
first
first
thing
thing
we
we
do
do
is
is
create
create
our
our
custom
custom
events,
events
which
which
we
we
do
do
with
with
the
the
output
output
decorator.
decorator
The
the
first
first
event
event
is
is
called
called
dropped
dropped
and
and
it
it
is
is
fired
fired
when
when
the
the
user
user
drops
drops
their
their
files
files
onto
onto
the
the
drop
drop
zone.
zone
The
the
event's
event's
going
going
to
to
emit
emit
a
a
file
file
list
list
which
which
contains
contains
the
the
actual
actual
files
files
or
or
file
file
that
that
we
we
want
want
to
to
upload
upload
to
to
Firebase.
firebase
I'm
i'm
setting
setting
up
up
a
a
second
second
event
event
here
here
called
called
hovered
hovered
just
just
to
to
emit
emit
a
a
boolean
boolean
based
based
on
on
whether
whether
or
or
not
not
the
the
user
user
is
is
hovering
hovering
over
over
the
the
element
element
we
we
can
can
toggle
toggle
some
some
CSS
css
classes.
classes
From
from
there,
there
we
we
can
can
use
use
host
host
listener
listener
to
to
listen
listen
to
to
the
the
drop
drop
event
event
from
from
the
the
browser.
browser
And
and
the
the
first
first
thing
thing
we
we
wanna
wanna
do
do
is
is
prevent
prevent
the
the
default
default
behavior
behavior
because
because
otherwise,
otherwise
the
the
browser
browser
is
is
going
going
to
to
want
want
to
to
open
open
up
up
a
a
new
new
tab.
tab
The
the
event's
event's
going
going
to
to
contain
contain
a
a
file
file
list
list
which
which
we
we
can
can
extract
extract
by
by
calling
calling
event
event
data
data
transfer
transfer
files,
files
and
and
we'll
we'll
emit
emit
that
that
through
through
our
our
dropped
dropped
event
event
emitter.
emitter
We'll
we'll
also
also
set
set
the
the
hover
hover
event
event
to
to
false.
false
That's
that's
the
the
most
most
important
important
part,
part
but
but
we
we
also
also
want
want
to
to
listen
listen
to
to
the
the
drag
drag
over
over
event
event
and
and
we'll
we'll
set
set
our
our
custom
custom
hover
hover
event
event
to
to
true
true
when
when
that
that
occurs.
occurs
Then
then
we
we
can
can
emit
emit
false
false
on
on
the
the
drag
drag
leave
leave
event.
event
And
and
we'll
we'll
also
also
wanna
wanna
prevent
prevent
default
default
on
on
these
these
events
events
as
as
well.
well
That
that
gives
gives
us
us
a
a
bare
bare
minimum
minimum
drop
drop
zone.
zone
Now
now
let's
let's
put
put
it
it
to
to
use
use
in
in
a
a
file
file
upload
upload
component.
component
The
the
goal
goal
here
here
is
is
to
to
give
give
you
you
a
a
pretty
pretty
extensive
extensive
tour
tour
the
the
new
new
functionality
functionality
in
in
the
the
storage
storage
module.
module
The
the
first
first
thing
thing
we'll
we'll
do
do
is
is
import
import
AngularFire
angularfire
storage
storage
and
and
the
the
AngularFire
angularfire
upload
upload
task.
task
From
from
there,
there
we're
we're
going
going
to
to
declare
declare
a
a
few
few
variables.
variables
The
the
main
main
part
part
of
of
AngularFire
angularfire
storage
storage
is
is
the
the
task.
task
It's
it's
the
the
object
object
that
that
gives
gives
us
us
access
access
to
to
the
the
observable
observable
data
data
and
and
allows
allows
us
us
to
to
pause,
pause
cancel,
cancel
or
or
zoom
zoom
and
and
upload.
upload
One
one
of
of
the
the
observables
observables
that
that
it
it
gives
gives
us
us
is
is
the
the
percentage
percentage
changes,
changes
which
which
is
is
really
really
useful
useful
if
if
you're
you're
doing
doing
something
something
like
like
showing
showing
a
a
progress
progress
bar.
bar
But
but
you
you
can
can
get
get
even
even
more
more
data
data
than
than
that
that
by
by
observing
observing
the
the
actual
actual
snapshot.
snapshot
When
when
the
the
upload
upload
is
is
complete,
complete
you're
you're
probably
probably
going
going
to
to
want
want
the
the
download
download
URL
url
which
which
you
you
can
can
also
also
listen
listen
to
to
as
as
an
an
observable.
observable
The
the
last
last
thing
thing
I'm
i'm
doing
doing
is
is
setting
setting
up
up
a
a
boolean
boolean
variable
variable
so
so
we
we
can
can
toggle
toggle
some
some
the
the
assess
assess
classes.
classes
The
the
next
next
step
step
is
is
to
to
inject
inject
AngularFire
angularfire
storage
storage
into
into
the
the
constructor.
constructor
Then
then
what
what
I
i
really
really
wanna
wanna
focus
focus
on
on
is
is
this
this
start
start
upload
upload
method
method
which
which
will
will
kick
kick
off
off
the
the
entire
entire
upload
upload
process.
process
This
this
method
method
is
is
an
an
event
event
handler,
handler
and
and
it
it
will
will
take
take
a
a
file
file
list
list
as
as
an
an
argument,
argument
which
which
we'll
we'll
get
get
from
from
our
our
directive
directive
that
that
we
we
defined
defined
earlier.
earlier
So
so
when
when
the
the
drop
drop
event
event
fires,
fires
it's
it's
going
going
to
to
start
start
the
the
upload.
upload
We
we
can
can
get
get
the
the
first
first
file
file
from
from
the
the
list
list
by
by
calling
calling
event
event
item
item
0.
0
A
a
file
file
list
list
is
is
kind
kind
of
of
like
like
an
an
array,
array
so
so
you
you
could
could
iterate
iterate
over
over
it
it
if
if
you
you
plan
plan
on
on
uploading
uploading
multiple
multiple
files
files
at
at
once.
once
The
the
next
next
thing
thing
you
you
might
might
wanna
wanna
do
do
is
is
provide
provide
some
some
client
client
side
side
validation.
validation
So
so
in
in
this
this
case,
case
we
we
only
only
want
want
the
the
user
user
to
to
be
be
able
able
to
to
upload
upload
image
image
files.
files
We
we
can
can
look
look
at
at
the
the
MIME
mime
type
type
on
on
the
the
file
file
that
that
was
was
selected.
selected
And
and
if
if
it's
it's
not
not
an
an
image,
image
we'll
we'll
just
just
go
go
ahead
ahead
and
and
console
console
error
error
and
and
return
return
from
from
this
this
function.
function
And
and
because
because
we
we
want
want
full
full
stack
stack
security,
security
we're
we're
going
going
to
to
mirror
mirror
this
this
logic
logic
in
in
our
our
back
back
end
end
Firebase
firebase
storage
storage
rules.
rules
To
to
do
do
that,
that
we
we
look
look
at
at
the
the
incoming
incoming
request
request
and
and
make
make
sure
sure
that
that
the
the
content
content
type
type
matches
matches
image.
image
Now
now
that
that
we
we
secured
secured
our
our
upload,
upload
we
we
need
need
to
to
tell
tell
Firebase
firebase
where
where
to
to
actually
actually
save
save
it.
it
Storage
storage
doesn't
doesn't
generate
generate
a
a
unique
unique
ID
id
like
like
the
the
Firestore
firestore
database
database
does.
does
So
so
it's
it's
generally
generally
a
a
good
good
idea
idea
to
to
give
give
your
your
file
file
path
path
some
some
sort
sort
of
of
unique
unique
identifier
identifier
so
so
it
it
doesn't
doesn't
get
get
overwritten
overwritten
by
by
a
a
file
file
of
of
the
the
same
same
name.
name
The
the
easiest
easiest
method
method
is
is
just
just
to
to
use
use
a
a
JavaScript
javascript
date
date
with
with
git
git
time
time
and
and
append
append
it
it
to
to
the
the
file
file
name.
name
That's
that's
going
going
to
to
make
make
file
file
name
name
collisions
collisions
extremely
extremely
unlikely.
unlikely
You
you
can
can
also
also
save
save
your
your
own
own
custom
custom
metadata
metadata
on
on
the
the
image
image
itself.
itself
There's
there's
probably
probably
a
a
ton
ton
of
of
different
different
use
use
cases.
cases
But
but
for
for
now,
now
I'm
i'm
just
just
going
going
to
to
pretend
pretend
that
that
I
i
have
have
multiple
multiple
apps,
apps
and
and
I
i
wanna
wanna
know
know
which
which
app
app
actually
actually
uploaded
uploaded
this
this
image.
image
Let's
let's
say
say
it
it
was
was
uploaded
uploaded
from
from
my
my
AngularFire
angularfire
powered
powered
progressive
progressive
web
web
app.
app
At
at
this
this
point,
point
we
we
have
have
everything
everything
we
we
need
need
to
to
define
define
the
the
actual
actual
upload
upload
task.
task
To
to
do
do
that,
that
we
we
call
call
storage
storage
upload
upload
and
and
we
we
pass
pass
the
the
file
file
path
path
as
as
well
well
as
as
the
the
file
file
itself
itself
and
and
an
an
object
object
of
of
our
our
custom
custom
metadata.
metadata
And
and
the
the
metadata
metadata
is
is
completely
completely
optional
optional
by
by
the
the
way.
way
When
when
we
we
call
call
upload,
upload
it's
it's
going
going
to
to
immediately
immediately
start
start
the
the
upload
upload
process.
process
There's
there's
no
no
need
need
to
to
call
call
subscribe
subscribe
on
on
it
it
like
like
you
you
would
would
with
with
an
an
observable.
observable
It
it
works
works
by
by
giving
giving
us
us
observables
observables
that
that
we
we
can
can
listen
listen
to
to
to
to
monitor
monitor
the
the
actual
actual
upload
upload
progress.
progress
We
we
get
get
the
the
observables
observables
by
by
calling
calling
percentage
percentage
changes
changes
and
and
snapshot
snapshot
changes.
changes
Up.
up
And
and
the
the
last
last
thing
thing
we'll
we'll
do
do
is
is
set
set
a
a
download
download
URL,
url
which
which
is
is
an
an
observable
observable
that
that
emits
emits
once
once
the
the
upload
upload
process
process
is
is
complete.
complete
Now
now
one
one
final
final
thing
thing
I'm
i'm
going
going
to
to
do
do
is
is
determine
determine
if
if
an
an
upload
upload
is
is
active
active
so
so
we
we
can
can
toggle
toggle
between
between
the
the
paused
paused
and
and
resume
resume
states.
states
Every
every
snapshot
snapshot
that
that
gets
gets
emitted
emitted
has
has
a
a
state
state
which
which
might
might
be
be
running
running
or
or
paused.
paused
And
and
we
we
can
can
also
also
look
look
at
at
the
the
bytes
bytes
transferred
transferred
and
and
compare
compare
them
them
to
to
the
the
total
total
bytes
bytes
in
in
the
the
file.
file
The
the
data
data
contained
contained
in
in
the
the
snapshot
snapshot
can
can
be
be
very
very
useful
useful
for
for
customizing
customizing
the
the
behavior
behavior
of
of
your
your
front
front
end
end
UI.
ui
Now
now
let's
let's
jump
jump
over
over
to
to
the
the
component
component
CSS
css
file.
file
I'm
i'm
not
not
really
really
going
going
to
to
talk
talk
about
about
the
the
CSS,
css
but
but
I
i
do
do
wanna
wanna
give
give
you
you
one
one
helpful
helpful
tip.
tip
The
the
snapshot
snapshot
emits
emits
data
data
in
in
chunks,
chunks
so
so
you
you
can
can
smooth
smooth
out
out
the
the
transition
transition
on
on
your
your
progress
progress
bar
bar
by
by
just
just
adding
adding
a
a
simple
simple
CSS
css
animation.
animation
In
in
this
this
case,
case
a
a
transition
transition
animation
animation
on
on
the
the
width
width
was
was
hugely
hugely
helpful
helpful
at
at
smoothing
smoothing
out
out
the
the
progress
progress
bar.
bar
Now
now
let's
let's
jump
jump
over
over
to
to
the
the
HTML
html
and
and
put
put
everything
everything
together.
together
1st,
1st
we'll
we'll
set
set
up
up
a
a
div
div
and
and
add
add
our
our
custom
custom
drop
drop
zone
zone
directive
directive
to
to
it.
it
That
that
will
will
give
give
us
us
access
access
to
to
our
our
hover
hover
event
event
to
to
toggle
toggle
the
the
CSS
css
class
class
and
and
also
also
to
to
our
our
dropped
dropped
event
event
to
to
know
know
when
when
the
the
files
files
were
were
dropped
dropped
in
in
this
this
div.
div
That
that
emits
emits
a
a
file
file
list,
list
which
which
will
will
pass
pass
on
on
to
to
our
our
start
start
upload
upload
method
method
to
to
immediately
immediately
start
start
the
the
upload
upload
process.
process
In
in
addition
addition
to
to
drag
drag
and
and
drop,
drop
we
we
also
also
wanna
wanna
give
give
it
it
just
just
plain
plain
file
file
upload
upload
button.
button
This
this
is
is
especially
especially
important
important
on
on
mobile
mobile
devices
devices
because
because
it
it
will
will
bring
bring
up
up
the
the
user's
user's
camera,
camera
which
which
will
will
allow
allow
them
them
to
to
either
either
take
take
a
a
picture
picture
or
or
select
select
an
an
existing
existing
picture
picture
on
on
their
their
device.
device
All
all
we
we
need
need
is
is
an
an
HTML
html
input
input
with
with
the
the
type
type
of
of
file,
file
and
and
then
then
we'll
we'll
bind
bind
it
it
to
to
the
the
change
change
event
event
and
and
fire
fire
off
off
the
the
same
same
start
start
upload
upload
method.
method
That's
that's
all
all
it
it
takes
takes
to
to
build
build
a
a
drop
drop
zone,
zone
but
but
we
we
also
also
wanna
wanna
show
show
a
a
progress
progress
bar.
bar
To
to
do
do
that,
that
we're
we're
going
going
to
to
use
use
the
the
percentage
percentage
observable
observable
that
that
we
we
set
set
in
in
the
the
component
component
type
type
script.
script
We
we
can
can
unwrap
unwrap
it
it
with
with
the
the
async
async
pipe
pipe
and
and
then
then
set
set
it
it
as
as
a
a
template
template
variable
variable
called
called
percent.
percent
It
it
emits
emits
a
a
number
number
ranging
ranging
from
from
0
0
to
to
100
100
and
and
we
we
can
can
use
use
it
it
as
as
the
the
value
value
in
in
our
our
progress
progress
bar.
bar
That's
that's
really
really
handy,
handy
but
but
we
we
can
can
also
also
take
take
this
this
a
a
step
step
further
further
and
and
unwrap
unwrap
the
the
snapshot
snapshot
in
in
the
the
HTML
html
as
as
well.
well
The
the
snapshot
snapshot
contains
contains
information
information
about
about
the
the
bytes
bytes
transferred
transferred
and
and
the
the
total
total
bytes
bytes
in
in
the
the
file.
file
That's
that's
not
not
very
very
user
user
friendly
friendly
by
by
itself,
itself
but
but
what
what
I
i
did
did
is
is
create
create
a
a
file
file
size
size
pipe
pipe
that
that
we'll
we'll
round
round
it
it
to
to
the
the
nearest
nearest
format
format
such
such
as
as
megabytes,
megabytes
kilobytes,
kilobytes
etcetera.
etcetera
The
the
pipe
pipe
was
was
really
really
easy
easy
to
to
create
create
because
because
I
i
borrowed
borrowed
all
all
the
the
source
source
code
code
from
from
the
the
wrangle.ioc
wrangle.ioc
Angular
angular
training
training
book
book
on
on
custom
custom
pipes,
pipes
and
and
I
i
recommend
recommend
you
you
do
do
the
the
same.
same
The
the
next
next
thing
thing
we
we
can
can
do
do
is
is
unwrap
unwrap
the
the
download
download
URL.
url
We
we
can
can
give
give
the
the
user
user
a
a
URL
url
to
to
download
download
the
the
file
file
directly.
directly
But
but
since
since
we're
we're
dealing
dealing
with
with
images
images
here,
here
we
we
can
can
also
also
set
set
that
that
URL
url
as
as
the
the
source
source
of
of
an
an
HTML
html
image.
image
Up.
up
Now
now
the
the
only
only
thing
thing
left
left
to
to
do
do
is
is
set
set
up
up
a
a
few
few
buttons
buttons
here
here
so
so
the
the
user
user
can
can
toggle
toggle
between
between
pause,
pause
cancel,
cancel
and
and
resume
resume
on
on
the
the
upload
upload
task.
task
Doing
doing
that
that
is
is
incredibly
incredibly
simple.
simple
All
all
we
we
have
have
to
to
do
do
is
is
set
set
up
up
a
a
button
button
and
and
bind
bind
the
the
task
task
pause
pause
method
method
to
to
the
the
click
click
event.
event
Then
then
we
we
only
only
want
want
the
the
user
user
to
to
be
be
able
able
to
to
fire
fire
this
this
if
if
the
the
upload
upload
is
is
actually
actually
active
active
at
at
the
the
time.
time
So
so
we
we
can
can
use
use
that
that
is
is
active
active
helper
helper
that
that
we
we
already
already
defined
defined
and
and
pass
pass
it
it
the
the
snapshot.
snapshot
We
we
also
also
have
have
a
a
cancel
cancel
method
method
on
on
the
the
task
task
which
which
we
we
can
can
set
set
up
up
in
in
the
the
exact
exact
same
same
way.
way
Then
then
if
if
the
the
download
download
is
is
paused,
paused
we
we
wanna
wanna
give
give
the
the
user
user
a
a
way
way
to
to
resume
resume
it.
it
So
so
to
to
do
do
that,
that
we
we
call
call
task
task
resume.
resume
And
and
this
this
button
button
should
should
be
be
disabled
disabled
unless
unless
the
the
snapshot
snapshot
state
state
equals
equals
paused.
paused
A.
a
And
and
just
just
like
like
that,
that
you
you
now
now
have
have
your
your
own
own
AngularFire
angularfire
drop
drop
zone.
zone
But
but
we're
we're
not
not
quite
quite
done
done
yet
yet
because
because
I
i
did
did
promise
promise
you
you
one
one
more
more
advanced
advanced
thing
thing
with
with
Firestore.
firestore
There's
there's
a
a
good
good
chance
chance
you'll
you'll
want
want
to
to
access
access
your
your
file
file
later
later
on
on
so
so
we
we
can
can
save
save
information
information
about
about
that
that
file
file
in
in
the
the
Firestore
firestore
database.
database
We
we
can
can
do
do
this
this
with
with
just
just
a
a
few
few
lines
lines
of
of
code.
code
First,
first
we'll
we'll
bring
bring
in
in
Firestore
firestore
and
and
the
the
tap
tap
operator
operator
from
from
RxJS.
rxjs
Then
then
we'll
we'll
inject
inject
AngularFirestore
angularfirestore
in
in
the
the
constructor.
constructor
Because
because
we
we
already
already
have
have
an
an
observable
observable
of
of
the
the
snapshot
snapshot
is
is
for
for
the
the
upload.
upload
We
we
can
can
pipe
pipe
in
in
the
the
tap
tap
operator
operator
to
to
make
make
a
a
call
call
to
to
our
our
database
database
once
once
the
the
upload
upload
is
is
complete.
complete
What
what
we
we
wanna
wanna
do
do
here
here
is
is
make
make
sure
sure
that
that
we
we
only
only
fire
fire
this
this
on
on
the
the
last
last
op
op
shot,
shot
which
which
is
is
going
going
to
to
happen
happen
when
when
the
the
bytes
bytes
transferred
transferred
equal
equal
the
the
total
total
bytes
bytes
of
of
the
the
file.
file
Then
then
we
we
can
can
simply
simply
make
make
reference
reference
to
to
our
our
Firestore
firestore
collections,
collections
which
which
I'll
i'll
call
call
photos,
photos
and
and
then
then
we'll
we'll
add
add
some
some
data
data
about
about
this
this
file.
file
The
the
only
only
important
important
piece
piece
of
of
data
data
to
to
save
save
here
here
is
is
the
the
file
file
path
path
because
because
you
you
can
can
retrieve
retrieve
that
that
from
from
your
your
database
database
and
and
then
then
make
make
a
a
call
call
to
to
storage
storage
using
using
the
the
get
get
download
download
URL
url
method
method
to
to
retrieve
retrieve
the
the
actual
actual
file.
file
Now
now
let's
let's
jump
jump
over
over
the
the
Firebase
firebase
console
console
and
and
make
make
sure
sure
everything
everything
works.
works
1st,
1st
we'll
we'll
look
look
in
in
our
our
storage
storage
bucket
bucket
just
just
to
to
make
make
sure
sure
our
our
images
images
are
are
being
being
uploaded
uploaded
along
along
with
with
their
their
associated
associated
metadata,
metadata
and
and
you
you
can
can
see
see
the
the
metadata
metadata
down
down
here
here
at
at
the
the
bottom.
bottom
Then
then
if
if
we
we
jump
jump
over
over
to
to
the
the
Firestore
firestore
database
database
console,
console
we
we
should
should
see
see
this
this
photos
photos
collection
collection
along
along
with
with
the
the
file
file
path
path
to
to
that
that
actual
actual
storage
storage
location.
location
In
in
other
other
words,
words
you
you
have
have
successfully
successfully
connected
connected
your
your
persistent
persistent
app
app
data
data
with
with
your
your
stored
stored
files.
files
I'm
i'm
going
going
to
to
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
you
you
can
can
look
look
forward
forward
to
to
a
a
whole
whole
bunch
bunch
more
more
videos
videos
in
in
the
the
near
near
future
future
involving
involving
AngularFire
angularfire
storage.
storage
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
see
see
you
you
soon.
soon
success
The speaker explains new features in AngularFinancial 2 storage module, including upholder files and control of upload progress, and guides the caller through building a new Angular 5 app. They also discuss the start upload method and use a unique identifier for file names. The speaker explains the process of setting up custom hover and leave events, including import Angularipping and setting up a variables for file upload task. They provide tips for creating a drop zone and setting up a task resume method, as well as activating a start upload method and saving file metadata for future reference.
AngularFire2 Storage -  File Upload Dropzone
Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before. In this episode, I'm going to take you through the new features in the AngularFire 2 storage module. Up then we'll use it to build a drop zone file uploader from scratch. In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload. There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com. Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works. When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket. You can then monitor the upload progress as an observable. The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback. When the process is complete, it will give you back the download URL that you can show in your front end UI. Now let's go ahead and build this thing. We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase. Then inside of your Angular environment, add your Firebase project config. And lastly, we'll go into the app module and initialize our AngularFire app. I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video. Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app. We want the user to drag and drop a file, which is a perfect use case for an Angular directive. We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity. We can create custom events in Angular by using a combination of host listener, output and event emitter. The first thing we do is create our custom events, which we do with the output decorator. The first event is called dropped and it is fired when the user drops their files onto the drop zone. The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase. I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes. From there, we can use host listener to listen to the drop event from the browser. And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab. The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter. We'll also set the hover event to false. That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs. Then we can emit false on the drag leave event. And we'll also wanna prevent default on these events as well. That gives us a bare minimum drop zone. Now let's put it to use in a file upload component. The goal here is to give you a pretty extensive tour the new functionality in the storage module. The first thing we'll do is import AngularFire storage and the AngularFire upload task. From there, we're going to declare a few variables. The main part of AngularFire storage is the task. It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload. One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar. But you can get even more data than that by observing the actual snapshot. When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable. The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes. The next step is to inject AngularFire storage into the constructor. Then what I really wanna focus on is this start upload method which will kick off the entire upload process. This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier. So when the drop event fires, it's going to start the upload. We can get the first file from the list by calling event item 0. A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once. The next thing you might wanna do is provide some client side validation. So in this case, we only want the user to be able to upload image files. We can look at the MIME type on the file that was selected. And if it's not an image, we'll just go ahead and console error and return from this function. And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules. To do that, we look at the incoming request and make sure that the content type matches image. Now that we secured our upload, we need to tell Firebase where to actually save it. Storage doesn't generate a unique ID like the Firestore database does. So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name. The easiest method is just to use a JavaScript date with git time and append it to the file name. That's going to make file name collisions extremely unlikely. You can also save your own custom metadata on the image itself. There's probably a ton of different use cases. But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image. Let's say it was uploaded from my AngularFire powered progressive web app. At this point, we have everything we need to define the actual upload task. To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata. And the metadata is completely optional by the way. When we call upload, it's going to immediately start the upload process. There's no need to call subscribe on it like you would with an observable. It works by giving us observables that we can listen to to monitor the actual upload progress. We get the observables by calling percentage changes and snapshot changes. Up. And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete. Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states. Every snapshot that gets emitted has a state which might be running or paused. And we can also look at the bytes transferred and compare them to the total bytes in the file. The data contained in the snapshot can be very useful for customizing the behavior of your front end UI. Now let's jump over to the component CSS file. I'm not really going to talk about the CSS, but I do wanna give you one helpful tip. The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation. In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar. Now let's jump over to the HTML and put everything together. 1st, we'll set up a div and add our custom drop zone directive to it. That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div. That emits a file list, which will pass on to our start upload method to immediately start the upload process. In addition to drag and drop, we also wanna give it just plain file upload button. This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device. All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method. That's all it takes to build a drop zone, but we also wanna show a progress bar. To do that, we're going to use the percentage observable that we set in the component type script. We can unwrap it with the async pipe and then set it as a template variable called percent. It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar. That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well. The snapshot contains information about the bytes transferred and the total bytes in the file. That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera. The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same. The next thing we can do is unwrap the download URL. We can give the user a URL to download the file directly. But since we're dealing with images here, we can also set that URL as the source of an HTML image. Up. Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task. Doing that is incredibly simple. All we have to do is set up a button and bind the task pause method to the click event. Then we only want the user to be able to fire this if the upload is actually active at the time. So we can use that is active helper that we already defined and pass it the snapshot. We also have a cancel method on the task which we can set up in the exact same way. Then if the download is paused, we wanna give the user a way to resume it. So to do that, we call task resume. And this button should be disabled unless the snapshot state equals paused. A. And just like that, you now have your own AngularFire drop zone. But we're not quite done yet because I did promise you one more advanced thing with Firestore. There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database. We can do this with just a few lines of code. First, we'll bring in Firestore and the tap operator from RxJS. Then we'll inject AngularFirestore in the constructor. Because we already have an observable of the snapshot is for the upload. We can pipe in the tap operator to make a call to our database once the upload is complete. What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file. Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file. The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file. Now let's jump over the Firebase console and make sure everything works. 1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom. Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location. In other words, you have successfully connected your persistent app data with your stored files. I'm going to wrap things up there. If this video helped you, please like and subscribe. And you can look forward to a whole bunch more videos in the near future involving AngularFire storage. Thanks for watching, and I'll see you soon.
The speaker explains new features in AngularFinancial 2 storage module, including upholder files and control of upload progress, and guides the caller through building a new Angular 5 app. They also discuss the start upload method and use a unique identifier for file names. The speaker explains the process of setting up custom hover and leave events, including import Angularipping and setting up a variables for file upload task. They provide tips for creating a drop zone and setting up a task resume method, as well as activating a start upload method and saving file metadata for future reference.

        [INST]
        You are youtuber called Fireship you make engaging high-intensity and entertaining coding tutorials and tech news. 
        you covers a wide range of topics relevant to programmers, aiming to help them learn and improve their skills quickly.
        
        Given the title of the video : AngularFire2 Storage -  File Upload Dropzone 
        and a small summary : The speaker explains new features in AngularFinancial 2 storage module, including upholder files and control of upload progress, and guides the caller through building a new Angular 5 app. They also discuss the start upload method and use a unique identifier for file names. The speaker explains the process of setting up custom hover and leave events, including import Angularipping and setting up a variables for file upload task. They provide tips for creating a drop zone and setting up a task resume method, as well as activating a start upload method and saving file metadata for future reference.
        [/INST]
        
        Generate the video : Firebase Storage is now officially supported by AngularFire 2, which means uploading files from an Angular application is easier than ever before. In this episode, I'm going to take you through the new features in the AngularFire 2 storage module. Up then we'll use it to build a drop zone file uploader from scratch. In addition to uploading files to Firebase Storage, it can also control the entire upload process by pausing, canceling, or resuming an upload. There's a whole bunch of other cool stuff I wanna show you, but first make sure to like and subscribe and grab the source code from angularfirebase.com. Before we jump into the code, I wanna give you a few more details about how the AngularFire 2 storage module works. When we drag and drop a file, it's going to start an AngularFire upload task, which will immediately start uploading the file to your Firebase storage bucket. You can then monitor the upload progress as an observable. The snapshot is emitted several times per second, so you can do things like update your progress or or just provide the user with some helpful feedback. When the process is complete, it will give you back the download URL that you can show in your front end UI. Now let's go ahead and build this thing. We'll start with a brand new Angular 5 app, and then inside that project, install AngularFire 2 and Firebase. Then inside of your Angular environment, add your Firebase project config. And lastly, we'll go into the app module and initialize our AngularFire app. I'm bringing in both the AngularFire storage module and the Firestore database for some advanced stuff I'll show you towards the end of the video. Now that we have AngularFire 2 set up, we need a way to retrieve a file from the user's device into our Angular app. We want the user to drag and drop a file, which is a perfect use case for an Angular directive. We want to use this directive on an HTML element and have it emit custom events based on certain drag and drop activity. We can create custom events in Angular by using a combination of host listener, output and event emitter. The first thing we do is create our custom events, which we do with the output decorator. The first event is called dropped and it is fired when the user drops their files onto the drop zone. The event's going to emit a file list which contains the actual files or file that we want to upload to Firebase. I'm setting up a second event here called hovered just to emit a boolean based on whether or not the user is hovering over the element we can toggle some CSS classes. From there, we can use host listener to listen to the drop event from the browser. And the first thing we wanna do is prevent the default behavior because otherwise, the browser is going to want to open up a new tab. The event's going to contain a file list which we can extract by calling event data transfer files, and we'll emit that through our dropped event emitter. We'll also set the hover event to false. That's the most important part, but we also want to listen to the drag over event and we'll set our custom hover event to true when that occurs. Then we can emit false on the drag leave event. And we'll also wanna prevent default on these events as well. That gives us a bare minimum drop zone. Now let's put it to use in a file upload component. The goal here is to give you a pretty extensive tour the new functionality in the storage module. The first thing we'll do is import AngularFire storage and the AngularFire upload task. From there, we're going to declare a few variables. The main part of AngularFire storage is the task. It's the object that gives us access to the observable data and allows us to pause, cancel, or zoom and upload. One of the observables that it gives us is the percentage changes, which is really useful if you're doing something like showing a progress bar. But you can get even more data than that by observing the actual snapshot. When the upload is complete, you're probably going to want the download URL which you can also listen to as an observable. The last thing I'm doing is setting up a boolean variable so we can toggle some the assess classes. The next step is to inject AngularFire storage into the constructor. Then what I really wanna focus on is this start upload method which will kick off the entire upload process. This method is an event handler, and it will take a file list as an argument, which we'll get from our directive that we defined earlier. So when the drop event fires, it's going to start the upload. We can get the first file from the list by calling event item 0. A file list is kind of like an array, so you could iterate over it if you plan on uploading multiple files at once. The next thing you might wanna do is provide some client side validation. So in this case, we only want the user to be able to upload image files. We can look at the MIME type on the file that was selected. And if it's not an image, we'll just go ahead and console error and return from this function. And because we want full stack security, we're going to mirror this logic in our back end Firebase storage rules. To do that, we look at the incoming request and make sure that the content type matches image. Now that we secured our upload, we need to tell Firebase where to actually save it. Storage doesn't generate a unique ID like the Firestore database does. So it's generally a good idea to give your file path some sort of unique identifier so it doesn't get overwritten by a file of the same name. The easiest method is just to use a JavaScript date with git time and append it to the file name. That's going to make file name collisions extremely unlikely. You can also save your own custom metadata on the image itself. There's probably a ton of different use cases. But for now, I'm just going to pretend that I have multiple apps, and I wanna know which app actually uploaded this image. Let's say it was uploaded from my AngularFire powered progressive web app. At this point, we have everything we need to define the actual upload task. To do that, we call storage upload and we pass the file path as well as the file itself and an object of our custom metadata. And the metadata is completely optional by the way. When we call upload, it's going to immediately start the upload process. There's no need to call subscribe on it like you would with an observable. It works by giving us observables that we can listen to to monitor the actual upload progress. We get the observables by calling percentage changes and snapshot changes. Up. And the last thing we'll do is set a download URL, which is an observable that emits once the upload process is complete. Now one final thing I'm going to do is determine if an upload is active so we can toggle between the paused and resume states. Every snapshot that gets emitted has a state which might be running or paused. And we can also look at the bytes transferred and compare them to the total bytes in the file. The data contained in the snapshot can be very useful for customizing the behavior of your front end UI. Now let's jump over to the component CSS file. I'm not really going to talk about the CSS, but I do wanna give you one helpful tip. The snapshot emits data in chunks, so you can smooth out the transition on your progress bar by just adding a simple CSS animation. In this case, a transition animation on the width was hugely helpful at smoothing out the progress bar. Now let's jump over to the HTML and put everything together. 1st, we'll set up a div and add our custom drop zone directive to it. That will give us access to our hover event to toggle the CSS class and also to our dropped event to know when the files were dropped in this div. That emits a file list, which will pass on to our start upload method to immediately start the upload process. In addition to drag and drop, we also wanna give it just plain file upload button. This is especially important on mobile devices because it will bring up the user's camera, which will allow them to either take a picture or select an existing picture on their device. All we need is an HTML input with the type of file, and then we'll bind it to the change event and fire off the same start upload method. That's all it takes to build a drop zone, but we also wanna show a progress bar. To do that, we're going to use the percentage observable that we set in the component type script. We can unwrap it with the async pipe and then set it as a template variable called percent. It emits a number ranging from 0 to 100 and we can use it as the value in our progress bar. That's really handy, but we can also take this a step further and unwrap the snapshot in the HTML as well. The snapshot contains information about the bytes transferred and the total bytes in the file. That's not very user friendly by itself, but what I did is create a file size pipe that we'll round it to the nearest format such as megabytes, kilobytes, etcetera. The pipe was really easy to create because I borrowed all the source code from the wrangle.ioc Angular training book on custom pipes, and I recommend you do the same. The next thing we can do is unwrap the download URL. We can give the user a URL to download the file directly. But since we're dealing with images here, we can also set that URL as the source of an HTML image. Up. Now the only thing left to do is set up a few buttons here so the user can toggle between pause, cancel, and resume on the upload task. Doing that is incredibly simple. All we have to do is set up a button and bind the task pause method to the click event. Then we only want the user to be able to fire this if the upload is actually active at the time. So we can use that is active helper that we already defined and pass it the snapshot. We also have a cancel method on the task which we can set up in the exact same way. Then if the download is paused, we wanna give the user a way to resume it. So to do that, we call task resume. And this button should be disabled unless the snapshot state equals paused. A. And just like that, you now have your own AngularFire drop zone. But we're not quite done yet because I did promise you one more advanced thing with Firestore. There's a good chance you'll want to access your file later on so we can save information about that file in the Firestore database. We can do this with just a few lines of code. First, we'll bring in Firestore and the tap operator from RxJS. Then we'll inject AngularFirestore in the constructor. Because we already have an observable of the snapshot is for the upload. We can pipe in the tap operator to make a call to our database once the upload is complete. What we wanna do here is make sure that we only fire this on the last op shot, which is going to happen when the bytes transferred equal the total bytes of the file. Then we can simply make reference to our Firestore collections, which I'll call photos, and then we'll add some data about this file. The only important piece of data to save here is the file path because you can retrieve that from your database and then make a call to storage using the get download URL method to retrieve the actual file. Now let's jump over the Firebase console and make sure everything works. 1st, we'll look in our storage bucket just to make sure our images are being uploaded along with their associated metadata, and you can see the metadata down here at the bottom. Then if we jump over to the Firestore database console, we should see this photos collection along with the file path to that actual storage location. In other words, you have successfully connected your persistent app data with your stored files. I'm going to wrap things up there. If this video helped you, please like and subscribe. And you can look forward to a whole bunch more videos in the near future involving AngularFire storage. Thanks for watching, and I'll see you soon.
        