When you need to check if a file already exists in your storage bucket, you can use the getDownloadURL() function.

It will return a string with the download URL of the file, or an error.

We can take advantage of that to listen on the specific error like this:

import { getStorage, ref, getDownloadURL } from 'firebase/storage';

function checkIfFileExists(filePath: string): Promise<boolean> {
  const storage = getStorage();
  const storageRef = ref(storage, filePath);

  getDownloadURL(storageRef)
    .then(url => {
      return Promise.resolve(true);
    })
    .catch(error => {
      if (error.code === 'storage/object-not-found') {
        return Promise.resolve(false);
      } else {
        return Promise.reject(error);
      }
    });
}
  • First, we import the functionality we’ll need from firebase/storage.
  • Then, we get the storage instance, and we create a reference to the file we’re looking for.
  • Lastly, we call the getDownloadURL() function passing that reference.
  • If the function returns successfully, we resolve the promise knowing the file is there.
  • If the function throws an error, we check if the error is storage/object-not-found, if so, we know the file isn’t there.

Or if you’re using @angular/fire, your code would look very similar, with only a couple of changes:

import {
  Storage,
  ref,
  getDownloadURL,
} from '@angular/fire/storage';

constructor(private readonly storage: Storage) {}

async getStorageDownloadUrl(filePath: string): Promise<string | boolean> {
    const storageRef = ref(this.storage, filePath);

    getDownloadURL(storageRef)
    .then(url => {
      return Promise.resolve(true);
    })
    .catch(error => {
      if (error.code === 'storage/object-not-found') {
        return Promise.resolve(false);
      } else {
        return Promise.reject(error);
      }
    });
}

Notice how we’re importing the functionality now from @angular/fire/storage instead, and we’re injecting the Storage instance into the constructor.