Introduction to Firebase's Storage
Tags: database, javascript, firebase
Published: 2017-12-11 17:03:42

---
title: Introduction to Firebase's Storage
published: true
description: Introduction to Firebase's Storage
tags: databases, javascript, firebase
---
In the [introduction to firebase's real-time database](https://dev.to/aurelkurtula/introduction-to-firebases-real-time-database-89l) tutorial I explained how we can use firebase to store, retrieve and edit data in a non-sql real-time database.

Storage is another service that firebase provides. Using this service we are able to upload and use files to google's cloud. Basically, we are able to upload our webpage assets and use them as if they were hosted in our own server. 

## Setting up our files

The [last tutorial](https://dev.to/aurelkurtula/introduction-to-firebases-real-time-database-89l) covered how to set up a fire base project. If you haven't read that, you definitely should. Then, you can simply continue with this tutorial.

Wellcome back :)

So, we have two files, the HTML an JavaScript file. The HTML  is going to have a file input button, that's how we will upload files.

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <title>Firebase Storage</title>
            <script type="text/javascript" src="https://www.gstatic.com/firebasejs/4.8.0/firebase.js"></script>
        </head>
        <body>
            <div id="uploading">
                    <progress value="0" max="100" id="progressBar">0%</progress>
                    <label for="submit">Click to upload</label>
                    <input type="file" value="upload" id="submitButton" />  
            </div>  
            <script type="text/javascript" src="script.js"></script>
        </body>
        </html>

As covered in the last tutorial, we have the filebase library at the top, our script file at the bottom. An input field to upload the file, where as the lable and progress are simply for decore! 

I'll leave the css up to you but to illustrate what we are doing, this is what I have (with the help of css)

![img](https://thepracticaldev.s3.amazonaws.com/i/zrx3ji1lm68heqdki8hv.png)

We'll need to use the initial Firebase configuration code, as we did in the [last tutorial](https://dev.to/aurelkurtula/introduction-to-firebases-real-time-database-89l), everything apart from the sections concerning the database. Add the following to the `script.js`:

        var config = {
          apiKey: "*******************",
          authDomain: "******.firebaseapp.com",
          databaseURL: "https://******.firebaseio.com",
          projectId: "******",
          storageBucket: "******.appspot.com",
          messagingSenderId: "***************"
        };
        firebase.initializeApp(config);

## Setting up storage restrictions

Just as we've done with the database, in order to play around with storage we need to remove the restrictions so that we can read and write without needing authentication. It's clearly a bad idea to do this in production but this is just to give us the freedom to learn this service in isolation.

All you need to do is navigate to `Storage` then `rules` and then edit read and write privileges to true

![img](https://thepracticaldev.s3.amazonaws.com/i/o0j15pp6kvhnp3728dgv.png)    

## Working with `storage()`

If you navigate to `Storage`, then `files` you'll see the message, "there are no files here yet". Our aim in this tutorial is to add files in there from our web app/site. 

Let's do that.

In `script.js` let's initialise the `Storage()` service.

    const storage = firebase.storage()

There's a two step process to uploading a file to the storage. Firstly we need to specify where we want the file to go and what name it should have.

    let locationRef = storage.ref('cats/cat1.jpg')

Above we are saying call the file `cat1.jpg` and add it into a folder cold `cats`.

So far that's just a reference, it does nothing, it simply waits for the file to be `put` into it. The following line actually pushes the local file to the firebase server.

    locationRef.put([the file])

### Uploading files to firebase storage

As you saw, there are only three lines of code to get an asset stored in the firebase storage. Now let's use those in combination with vanilla JavaScript to make actual uploads. 

In our HTML we had this code 

    <label for="submit">Click to upload</label>
    <input type="file" value="upload" id="submitButton" /> 

A user clicks on the input/label, then is required to select an asset and finally we want to upload that asset to firebase

    const storage = firebase.storage()
    const submitButton = document.getElementById('submitButton');
    submitButton.addEventListener('change', (e)=>{
      let file = e.target.files[0];
      let locationRef = storage.ref('cats/' + file.name)
      locationRef.put(file)
    })

As you can see, the exact same lines. This time the name of the file will be the same name of the local file, and the file being pushed to the server is the file itself. 

If you go back to the firebase console, to `Storage`, you'll see your cats folder and inside it, your cat photos! 

![](https://thepracticaldev.s3.amazonaws.com/i/65hooqflvqctkoc037uy.png)

### Getting feedback from the process

As usuall when considering user experience we need to be able to provide information through out the process. For example it be cool to know: 

- How long the upload is taking?
- did it actually upload successfully?
- What is the new location address?

Similar to the `database()` service, `storage()` also has an `on()` method which observes `state_changed` observer, within which we are able to observe the uploading process, catch any errors, and be aware when the upload is complete. 

    submitButton.addEventListener('change', (e)=>{
      let file = e.target.files[0];
      let locationRef = storage.ref('cats/' + file.name)
      let task = locationRef.put(file)
      task.on('state_changed',
          function progress(snapshot){
            // whilst uploading
          },
          function error(error){
            //error handling
          },
          function complete(){
            // on completion
          }
      )
    })

Note how we attached `locationRef.put(file)` to a variable, now we are able to observe it's state throughout the process:

    task.on('state_changed', 
      function progress(snapshot){ //progress
        let per = (snapshot.bytesTransferred / snapshot.totalBytes) *100;
        uploader.value = per;
      },
      function error(error){ },
      function complete(){
        console.log('Done') 
      }
    )

The first function watches the process, and as you can see, it gives us the total number of bytes of the original file, and the number of bytes that have been uploaded. We are using those numbers to get a percentage and we are adding that to the progress. Incase it's confusing `uploader` refers to the `progress` element: 

    <progress value="0" max="100" id="progressBar">0%</progress>    
    let uploader = document.getElementById('progressBar')

## Reading files from storage 

In order to get a file out of storage, you need to know the folder it's in and its file name. With that the full url can be found.

    let storageRef = storage.ref('cats')
    let image = storageRef.child('cat1.png');

The above can be writen in one line as we'll see later on:

    let storageRef = storage.ref('cats/cat.png');

To get the actual url and display it on the page: 

    image.getMetadata().then(function(metadata) {
      document.getElementById('img').src = metadata.downloadURLs[0]
    }).catch(function(error) { /*error handling*/ });    

Assuming we had an image tag with the id of `img`, the cat from storage would be sat on the browser :)

## Deleting files

Deleting is just as simple as everything else, follows the same pattern: point to the file, then run `delete()` on it

    let storageRef = storage.ref('cats/cat.png');
    storageRef.delete().then(function() {
      // removed
    }).catch(function(error) {
      // not removed :(
    });

## Combining storage with the database

I should end the tutorial here but just because the main reason I can think of that google gave storage with firebase is so that it can be used with the database, I am going to combine the two right now!    

Let's revisit the event listener from above: 

    submitButton.addEventListener('change', (e)=>{
      let file = e.target.files[0];
      let locationRef = storage.ref('cats/' + file.name)
      let task = locationRef.put(file)
      task.on('state_changed',
          ...
          function complete(){
            // on completion
          }
      )
    })

When the uploading is complete we want to store the full url to the database. 

You can easily do this yourself by following the [last tutorial](https://dev.to/aurelkurtula/introduction-to-firebases-real-time-database-89l)

    const database = firebase.database()
    const ref = database.ref('cats');
    submitButton.addEventListener('change', (e)=>{
      ...
      task.on('state_changed',
          ...
          function complete(){
            storageRef.getMetadata().then(metadata=>{
             ref.push({
              url: metadata.downloadURLs[0]
            })
            })
          }
      )
    })

Exactly the same as in the [last tutorial](https://dev.to/aurelkurtula/introduction-to-firebases-real-time-database-89l), in lines 1-2 we define the database service and where the content should go. Inside `complete` function (which doesn't have to have a name, as you know) we push to the database. Now if you check the database, you'll see a `cats` node and a child node with the cat url. **Note that `metadata` gives more information, such as the time when the file was uploaded and so you can get more information to store in the database.**

## Conclusion

This was fun. Stay tuned for few more tutorials on firebase. I have authentication to cover, and production mode (covering how we can protect the configuration settings), then anything else that I might think of conserning firebase services.