Uploading Images to Firebase

Uploading Images to Firebase

In this article, I am specifically going to address the issue of Uploading the Images to the Firebase Storage and then Displaying them to the Front-End using React.

Before you jump into reading the passage further, it's highly recommended to first take a look at "Authentication using Firebase" as this is connected to the Authentication of User.

Flow of Project

--> User Registration 
--> User Login 
--> Displaying User Profile --> Uploading Image to Firebase Storage
                            --> Displaing Images as soon as they are uploaded

Firebase Setup

  • Go to the Firebase console and select the existing project which you created earlier. Check "Authentication using Firebase" for reference.

  • Select Storage option in the sidebar and click on Get Started.

  • Go to the "Rules" tab and paste the following rules:

rules_version = '2';

service firebase.storage {
  match /b/{bucket}/o {
    match /images/{userId}/{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth != null && request.auth.uid == userId;
    }
  }
}
  • Click on Publish button.

Coding starts here

  1. Jump to "profile.jsx" inside your existing project directory.

  2. Make the following changes to your code:

/* eslint-disable no-unused-vars */
import React, { useEffect, useState } from 'react';
import { Link, Navigate } from 'react-router-dom';
import { auth, firestore, storage } from '../../firebase';
import { collection, doc, getDoc } from 'firebase/firestore';
import { ref, uploadBytes, listAll, getDownloadURL } from 'firebase/storage';
import { v4 as uuidv4 } from "uuid";
import './Profile.css';

function Profile() {
  const [fullName, setFullName] = useState('');
  const [isLoading, setLoading] = useState(true);
  const [imageUpload, setImageUpload] = useState(null);
  const [imageList, setImageList] = useState([]);

  // For displaying UserName
  useEffect(() => {
    const fetchUserData = async () => {
      try {
        const user = auth.currentUser;

        if (user) {
          const userDocRef = doc(collection(firestore, 'users'), user.uid);
          const userDocSnapshot = await getDoc(userDocRef);

          if (userDocSnapshot.exists()) {
            const userData = userDocSnapshot.data();
            setFullName(userData.fullName);
          }
        }
      } catch (error) {
        console.error(error);
      }

      setLoading(false);
    };

    fetchUserData();
  }, []);

  // For fetching and displaying Images
  useEffect(() => {
    const fetchImages = async () => {
      try {
        const user = auth.currentUser;

        if (user) {
          const userId = user.uid;
          const imageListRef = ref(storage, `images/${userId}/`);

          const response = await listAll(imageListRef);

          const urls = await Promise.all(
            response.items.map(async (item) => {
              const downloadURL = await getDownloadURL(item);
              return downloadURL;
            })
          );

          setImageList(urls);
        }
      } catch (error) {
        console.error(error);
      }
    };

    fetchImages();
  }, []);

  const uploadImage = () => {
    if (imageUpload == null) return;

    const user = auth.currentUser;

    if (user) {
      const userId = user.uid;
      const imageRef = ref(storage, `images/${userId}/${imageUpload.name}_${uuidv4()}`);

      uploadBytes(imageRef, imageUpload)
        .then(() => {
          alert("Image uploaded successfully");
          // Fetch and update the image list after successful upload
          fetchImages();
        })
        .catch((error) => {
          console.error(error);
        });
    }
  };

  const fetchImages = async () => {
    try {
      const user = auth.currentUser;

      if (user) {
        const userId = user.uid;
        const imageListRef = ref(storage, `images/${userId}/`);

        const response = await listAll(imageListRef);

        const urls = await Promise.all(
          response.items.map(async (item) => {
            const downloadURL = await getDownloadURL(item);
            return downloadURL;
          })
        );

        setImageList(urls);
      }
    } catch (error) {
      console.error(error);
    }
  };

  if (isLoading) {
    return <p>Loading...</p>;
  }

  if (!auth.currentUser) {
    return <Navigate to="/login" />;
  }

  return (
    <>
      <div className="container">
        <div className="form-container">
          <h2>Welcome, {fullName}!</h2>
          <br />
          <p>This is your profile page.</p>
          <br />
          <p>
            Go back to <Link to="/login">Login</Link> page.
          </p>
        </div>
      </div>

      <div className="container">
        <div className='input-container'>
          <input
              type="file"
              onChange={(event) => {
                setImageUpload(event.target.files[0]);
              }}
            />
            <button onClick={uploadImage}>Upload</button>
        </div>
      </div>


      <div className='images'>
        {imageList.map((url) => {
            return <img key={url} src={url} alt='img' />;
        })}
      </div>


    </>
  );
}

export default Profile;
  • The first useEffect fetches the user's data from Firestore and updates the fullName state.

  • The second useEffect fetches the list of images for the user from Firebase Storage and updates the imageList state.

  • The uploadImage function handles the image upload process and updates the image list after a successful upload.

  • The fetchImages function fetches the list of images for the user from Firebase Storage.

  • Another useEffect hook listens for changes in the authentication state and redirects to the login page if the user is not authenticated.

Inside your Firebase.js, add the following statement in the Header section:

import { getStorage } from "firebase/storage";

Add this code at the last:

const storage = getStorage(app);

export { app, auth, firestore, storage };

That's it!! You have successfully implemented User Authentication using Firebase which provides a profile page where Authenticated users can Upload and View images.

Project Snippets

Conclusion

You have successfully made a Project using Firebase and React JS which provides a profile page where Authenticated users can Upload and View images.

In case you are facing any difficulties or to get the full source code of this project, simply DM me on my LinkedIn.