66
votes

Following this example, I keep getting the error:

 TypeError: firebase.storage is not a function

From this line in my code:

var storageRef = firebase.storage().ref();

(And when I simply try to initialize storage from the storage guide, linked from firebase's npm site, I get the same error.)

In my Node.js project, I'm including the following libraries:

  • const firebase = require('firebase');
  • var admin = require('firebase-admin');
  • const fs = require('fs');

Up to this point, I've successfully been able to read from and write to the firebase database, creating a reference to the database with var db = admin.database(), then var ref = db.ref("/")... So I know I've configured Firebase and firebase-database correctly. But I'm stuck on storage, and have tried both admin.storage().ref() and firebase.storage().ref(), and firebase.storage().ref("/") with the same error message.

I've also tried:

var storage = firbase.storage();
var storageRef = storage.ref();

and

const app = firebase.initializeApp(config);
var storage = app.storage();

and with ref()'s void argument () and with "/"... but have the same message, yet to no avail.

I'm using:

  • "firebase": "^3.6.4"
  • "firebase-admin": "^4.0.4"
  • Node.js : v6.9.1

What must I do to successfully create a reference to storage?

15
@SergChernata No, it's a different error entirely. "Firebase is not a function. Their error was they did not initialize Firebase properly, whereas I did, and able to utilize the Firebase database and other features accordingly. Firebase Storage is the issue.NonCreature0714
What do you see when inspecting the firebase.storage object? Try to do console.log(JSON.stringify(firebase.storage)). Is it undefined?Selfish
Yes, it's undefined; despite the JSON pointing to the correct URL, which I just double-checked.NonCreature0714

15 Answers

30
votes

DEPRECATED, see below:

According to this answer, instead of firebase storage, in Node.js, google-cloud package storage should be used, and it seems that this answer should confirm it. Code example:

npm i --save google-cloud

Then:

const gcloud = require('google-cloud')

const storage = gcloud.storage({
    projectId: '<projectID>',
    keyFilename: 'service-account-credentials.json',
});

const bucket = storage.bucket('<projectID>.appspot.com')

As of 2018, this is the correct answer:

Or using only the storage part of the package:

npm install --save @google-cloud/storage

And then:

var storage = require('@google-cloud/storage')

Also check the docs for more.

96
votes

I faced the same problem. In my case, I needed to include storage module besides Firebase core.

import firebase from 'firebase/app';
import 'firebase/storage';  // <----

firebase.initializeApp({
  ...
});
const storageRef = firebase.storage().ref();

(npm firebase v5.0.4)

19
votes

Deprecated: please see the accepted answer.

Some details to note:

  1. Firebase Storage is no longer used with Node.js, so all documentation there is useless for Node.js. Instead, use google-cloud. The references and guides for Firebase and Google Cloud do not reflect this as of today.
  2. Unlike Firebase, google-cloud costs money, even for small projects.
  3. In my case, I'm using the firebase-admin SDK so I don't have to mess with user authentication at the moment.

Purpose

To create a single Node.js project which uses Firebase and Google Cloud. Why? Firebase has a useful database, among other features, and Google Cloud allows cloud file storage and retrieval.

Directions

Step 1: Project Creation

Create Firebase and Google Cloud (Storage) projects.

Step 2: Install Packages

Using npm, install firebase-admin and google-cloud in Node.js project.

Note 1: I used the admin SDK, so after creating the Firebase project, you'll need to go to:

  • Settings(the gear) > Project Settings > Service Accounts > Firebase Admin SDK
  • Then you: Select Node.js > [Copy/paste the generated code into your project] > [click "Generate New Private Key"] > [download the generated json to preferred location] > [replace "path/to...AccountKey.json" with the path to the key you just generated]

Note 2: the generated key can be reused in firebase or google-cloud credentials.

Step 3: Firebase Setup

Once your project is created, import the firebase-admin sdk:

The code should look like this, but filled with your info:

var admin = require("firebase-admin");
admin.initializeApp({
  credential: admin.credential.cert("/path/to/generated/json/here.json"),
  databaseURL: "database-url-from-firebase"
});

To find the databaseURL, go to 'Storage' in Firebase, and note the URL starting with gs: and copy/paste it the the value field of databaseURL.

Next, get a reference to the database you can use:

var db = admin.database();
var ref = db.ref("/");
console.log('DB ref: ' + ref); //just to debug, if undefined, there's a problem.

To learn more about reading/writing to the database, follow Firebase's own documentation.

Step 4: Google-Cloud Billing Setup

After creating a project on Google Cloud, add billing information; buckets cannot be used without billing info.

Step 5: Google-Cloud Storage Setup

  1. Scrolling through the menu (the horizontal 3-bars), click "Storage", then "Enable Billing". Yes, you added billing info, now you need to enable it for that project's buckets.
  2. You should see that a bucket should already exists from your Firebase project.
  3. Click on menu again(3-bar icon), then > IAM & Admin > Settings
  4. At settings, you'll see "Project ID" which should look like "projectName-00000" or "projectName-Some#", copy that project ID

Step 6: Google Cloud in Node.js

In your index.js:

var gcloud = require('google-cloud');
var gcs = gcloud.storage({
  projectId: 'paste-that-project-id-here',
  keyFilename: 'paste-that-path-to-the-previously-downloaded-json-from-firebase-here'
});

Now you can send a file to your storage by:

var bucket = gcs.bucket('bucket_name');
var remoteFile = bucket.file('somefile-inThisCaseASong.mp3');
var localFilename = '/Users/you/Music/somefile-inThisCaseASong.mp3';
bucket.upload(localFilename, function(err, file) {
  if (!err) {
    console.log('somefile-inThisCaseASong.mp3 is now in your bucket.');
  } else {
    console.log('Error uploading file: ' + err);
  }
});

Step 7: Verify

If the file is visible in Firebase Storage and Google Cloud Storage, you're done!

8
votes

Year 2020 answer, In my case I include firebase-storage.js in .html file

<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-storage.js"></script>  

Therefore, if you use all Firebase service, you will have

<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-firestore.js"></script>  
<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-messaging.js"></script>  
<script src="https://www.gstatic.com/firebasejs/6.5.0/firebase-storage.js"></script>  


<!-- your script calling Firebase Firestore under this line -->
<script> 
....
</script>
7
votes

When using Storage with Firebase, you're correct that you can't add buckets on the free tier. However, you DO get a bucket (just one) by default. My (eventually) successful approach was to:

  1. Add Storage to my project in Firebase (NOT Google Cloud)

  2. Add the Admin SDK and set up the necessary Service Account as per the Google Docs: https://firebase.google.com/docs/admin/setup?authuser=1

  3. Add the @google-cloud/storage package as per the instructions on using the Admin SDK with storage: https://firebase.google.com/docs/storage/admin/start?authuser=1

  4. Initialize the app:

    admin.initializeApp({
      credential: admin.credential.cert("/path/to/generated/json/here.json"),
      storageBucket: "folder-URL-from-Storage-page-excluding-gs://"
    });
    
  5. Access the bucket object with (from Admin SDK docs):

    const bucket = admin.storage().bucket();

  6. Operate on the bucket with the storage library. Example:

    bucket.upload('/path/file.ext', function(err, file, apiResponse) {
      //Do Stuff
    });
    

NOTE: I spent a couple of hours convinced it wasn't working because I didn't have a bucket, but it turned out my mistake was including the gs:// in the path to my storage bucket when initializing.

5
votes

I had the same problem, I had my code as following:

import * as firebase from "firebase/app";
import 'firebase/storage';

firebase.initializeApp({
  ...
});
const storageRef = firebase.storage().ref();

So, I found that way is only if you use Typescript.

If you use only ES6, then you must have:

import firebase from 'firebase/app';
import 'firebase/storage';

firebase.initializeApp({
  ...
});
const storageRef = firebase.storage().ref(); 

If you use ES5, then you must have:

var firebase = require("firebase/app");
require("firebase/storage");

firebase.initializeApp({
  ...
});
const storageRef = firebase.storage().ref();

Moreover, you can also use the following way but it is not recommended because you load all services (database,auth,storage,etc):

import firebase from "firebase";

firebase.initializeApp({
  ...
});
const storageRef = firebase.storage().ref();

Tested with Firebase 7.15.2

2
votes

I was able to use firebase.storage(), but it took some time to figure it out. It only works when importing like this:

//Importing
const firebase = require('firebase')
require('firebase/storage')

//Calling the function (You can call it normally then)
const storageRef = firebase.storage().ref();

I'm serious, whenever trying to import as firebase.storage() or doing anything different it wouldn't work! Hope it helps some of you guys.

2
votes

make sure you have added a script tag with this src in you HTML file < src="https://www.gstatic.com/firebasejs/7.12.0/firebase-storage.js" to your project

  • Here 7.12.0 will be replaced with your current working version.
0
votes

Does it change if you try to do it like the following?

// Initialize the default app:
const app = firebase.initializeApp(appConfig)

// Initialize storage from the *app* object:
const storage = app.storage()

From the docs, it seems that this is an alternate method. I prefer this one, as this links the storage to the app, making the code more readable, and more functional

0
votes

It looks like they have fixed it in a new version of the library. Just run npm update on the relevant package(s) and it should work.

0
votes

I encounter the same problem when I test my app locally, but everything works when the project is deployed.

This way, I actually use the following workaround :

if (!firebase.storage) {
    // prevent crash when working locally
    return;
}
let ref = firebase.storage().ref()
// perform production stuff ...

It's a little bit curious, but it works in my case.

0
votes

The firebase storage service still works (and AFAIK is not deprecated) in browsers. The firebase storage service is not available on server environments including during server-side-rendering.

This is how I've done it:

// only import uploadHandler client-side.
const uploadHandler = typeof window === 'object' ? require('./handlers').imageHandler : () => false; // ssr only

Then in handlers.js you can safely use the firebase storage service normally.

import * as firebase from 'firebase'
const storageRef = firebase.storage().ref();
const bucketObjectRef = storageRef.child('myFile.jpg');

As of 4/3/2020, it seems the entire firebase suite of products is still supported in browser environments.

firebase environment support table

Source: https://firebase.google.com/docs/web/setup#namespace

0
votes

I encountered a similar problem when I was integrating firebase's storage on the browser (webapp)

  <script src="https://www.gstatic.com/firebasejs/7.15.0/firebase-storage.js"></script>

Just add that line, and the bug is gone!

0
votes

in app.module initilize import firebase from 'firebase/app'; import 'firebase/storage';

firebase.storage();

-1
votes

import * as firebase from 'firebase/app';

Then firebase.storage().ref() should work.

Hope this helps.