Firebase storage provides a simple way of storing user-generated data like images, videos, and audio files. It integrates with Firebase authentication, so you can control who has access to the files.

You can store large amounts of content using Firebase since it automatically scales to fit your needs. It's simple to use with a third-party framework like the React JavaScript library

Project Setup

To upload files to Firebase storage, you need to create a web form that allows users to select a file from the file system.

Start by creating a React app using create-react-app. Run this command to generate a React project called firebase-upload:

        npx create-react-app firebase-upload

To keep it simple, you only need an input button that accepts files and an upload button. Replace the contents of App.js with the following code.

        import {useState} from "react"
 
function App() {
    const [file, setFile] = useState("");
 
    // Handles input change event and updates state
    function handleChange(event) {
        setFile(event.target.files[0]);
    }
 
    return (
        <div>
            <input type="file" accept="image/*" onChange={handleChange}/>
            <button>Upload to Firebase</button>
        </div>
    );
}
 
export default App;

In the above code, the input tag's accept attribute is set to only allow images. The handleChange() function handles the input change and updates the state to store the picked file.

Set Up Firebase

Before uploading the file to Firebase storage, you need to create a Firebase project.

Create a Firebase Project

Follow the instructions below to create a Firebase project:

  1. Go to the Firebase console page and click on Add project or Create a project (if you're creating a project for the first time).
  2. Give your project a name of your choice and click Continue.
    A Firebase project creation form requesting a project name
  3. Deselect Google Analytics since you don’t need it for this project and click Create project.
    A Firebase project creation form with the Google analytics option deselected
  4. Click Continue once the project is ready.
  5. Click on the web icon on the project overview page to register a web app.
    Firebase project overview page
  6. Give your app a nickname and click Register.
  7. Copy the configuration object provided. You'll need it to connect your application to Firebase.

Create a Cloud Storage Bucket

Firebase stores files in a cloud storage bucket. Follow the following steps to create it:

  1. On the project overview page, click on the Storage tab on the left navigation panel.
    Firebase project overview page showing the storage section
  2. Click Get Started and select test mode.
    Firebase configuration page showing cloud storage setup
  3. Select the default storage bucket location and click Done.

You're now ready to start uploading files to Firebase storage.

Add Firebase to React

In your terminal, navigate to your React project folder. Run the following command to install the Firebase SDK:

        npm install firebase

Create a new file, firebaseConfig.js, and initialize Firebase.

        import { initializeApp } from "firebase/app";
import { getStorage } from "firebase/storage";
 
// Initialize Firebase
const app = initializeApp ({
    apiKey: <apiKey>,
    authDomain: <authDomain>,
    projectId: <projectId>,
    storageBucket: <storageBucket>,
    messagingSenderId: <messagingSenderId>,
    appId: <appId>,
    measurementId: <measurementId>,
});
 
// Firebase storage reference
const storage = getStorage(app);
export default storage;

Use the configuration object you got after creating the Firebase project to initialize the Firebase app.

The final line exports the Firebase storage reference so you can access that instance from the rest of your app.

Create a Handler Function to Upload the Images to Firebase

Clicking the upload button should trigger the function responsible for uploading the file to Firebase storage. Let’s create that function.

In App.js, add the function handleUpload. In the function, check if the file is non-empty since a user might click on the upload button before choosing a file. If the file does not exist, raise an alert that tells the user to upload a file first.

        function handleUpload() {
    if (!file) {
        alert("Please choose a file first!")
    }
}

If the file exists, create a storage reference. A storage reference acts as a pointer to the file in the Cloud you want to operate on.

Start by importing the storage service you created in the firebaseConfig.js file.

        import storage from "./firebaseConfig.js"

Import ref from the Firebase storage instance and pass in the storage service and file path as an argument.

        import {ref} from "firebase/storage"
 
function handleUpload() {
    if (!file) {
        alert("Please choose a file first!")
    }
 
    const storageRef = ref(storage, `/files/${file.name}`)
}

Next, create an upload task by passing the Firebase storage instance to the uploadBytesResumable() function. There are several methods you can use, but this particular one allows you to pause and resume an upload. It also exposes progress updates.

The uploadBytesResumable() function accepts the storage reference and the file to upload.

        import {
    ref,
    uploadBytesResumable
} from "firebase/storage";
 
function handleUpload() {
    if (!file) {
        alert("Please choose a file first!")
    }
 
    const storageRef = ref(storage, `/files/${file.name}`)
    const uploadTask = uploadBytesResumable(storageRef, file);
}

To monitor the progress and handle errors as the file uploads, listen for state changes, errors, and completion.

        import {
    ref,
    uploadBytesResumable,
    getDownloadURL
} from "firebase/storage";
 
function handleUpload() {
    if (!file) {
        alert("Please choose a file first!")
    }
 
    const storageRef = ref(storage,`/files/${file.name}`)
    const uploadTask = uploadBytesResumable(storageRef, file);
 
    uploadTask.on(
        "state_changed",
        (snapshot) => {
            const percent = Math.round(
                (snapshot.bytesTransferred / snapshot.totalBytes) * 100
            );
 
            // update progress
            setPercent(percent);
        },
        (err) => console.log(err),
        () => {
            // download url
            getDownloadURL(uploadTask.snapshot.ref).then((url) => {
                console.log(url);
            });
        }
    );
}

Here, the state_changed event has three callback functions. In the first function, you're keeping track of the upload progress and uploading the progress state. In the second callback function, handle an error if the upload is unsuccessful.

The final function runs once the upload is complete, and gets the download URL, then displays it on the console. In a real-life application, you could save it in a database.

You can display the progress state of the upload using the percent state. Also add an onClick event on the upload button to trigger the handleUpload function.

        import {  useState } from "react";
 
function App() {
    const [percent, setPercent] = useState(0);
 
    return (
        <div>
            <input type="file" onChange={handleChange} accept="" />
            <button onClick={handleUpload}>Upload to Firebase</button>
            <p>{percent} "% done"</p>
        </div>
    )
}

Here's the complete code for App.js:

        import { useState } from "react";
import { storage } from "./firebaseConfig";
import { ref, uploadBytesResumable, getDownloadURL } from "firebase/storage";
 
function App() {
    // State to store uploaded file
    const [file, setFile] = useState("");
 
    // progress
    const [percent, setPercent] = useState(0);
 
    // Handle file upload event and update state
    function handleChange(event) {
        setFile(event.target.files[0]);
    }
 
    const handleUpload = () => {
        if (!file) {
            alert("Please upload an image first!");
        }
 
        const storageRef = ref(storage, `/files/${file.name}`);
 
        // progress can be paused and resumed. It also exposes progress updates.
        // Receives the storage reference and the file to upload.
        const uploadTask = uploadBytesResumable(storageRef, file);
 
        uploadTask.on(
            "state_changed",
            (snapshot) => {
                const percent = Math.round(
                    (snapshot.bytesTransferred / snapshot.totalBytes) * 100
                );
 
                // update progress
                setPercent(percent);
            },
            (err) => console.log(err),
            () => {
                // download url
                getDownloadURL(uploadTask.snapshot.ref).then((url) => {
                    console.log(url);
                });
            }
        );
    };
 
    return (
        <div>
            <input type="file" onChange={handleChange} accept="/image/*" />
            <button onClick={handleUpload}>Upload to Firebase</button>
            <p>{percent} "% done"</p>
        </div>
    );
}
 
export default App;

Doing More With Firebase Storage

Uploading files is one of the most basic features of Firebase storage. However, there are other things that Firebase storage allows you to do. You can access, display, organize, and delete your files.

In a more complicated app, you might want to authenticate users to give them permission to interact with only their files.