TypeError: firebase.storage is not a function

75,897

Solution 1

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.

Solution 2

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)

Solution 3

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!

Solution 4

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>

Solution 5

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

Share:
75,897
NonCreature0714
Author by

NonCreature0714

Software Engineer. Passionate about Open Source. Love Docker, Swift, Python, Rust, Raspberry Pi, Angular, iOS, and Unity3d.

Updated on July 05, 2022

Comments

  • NonCreature0714
    NonCreature0714 almost 2 years

    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?

  • NonCreature0714
    NonCreature0714 over 7 years
    No change... unless a new error counts... On the line, var storage = app.storage(); I get this error: TypeError: app.storage is not a function... And I did do this: var app = firebase.initializeApp(config); before hand.
  • Selfish
    Selfish over 7 years
    I understand this didn't work, and I'll add a second answer with a better try. That said, I'll leave this one here for potential web-coding googlers who may find themselves here. :)
  • NonCreature0714
    NonCreature0714 over 7 years
    Already ran into a warning...npm WARN deprecated [email protected]: gcloud has been renamed to google-cloud. To get new features and bug fixes, you must use the new package.... So I'll post this to keep the info up-to-date... working through this now, thanks to this second answer...
  • Selfish
    Selfish over 7 years
    Corrected the answer to reflect change. Thanks!
  • NonCreature0714
    NonCreature0714 over 7 years
    Just found a major unadvertised obstacle... You have to enable billing to use a bucket 😑
  • NonCreature0714
    NonCreature0714 over 7 years
    Your answer got me to the correct track, thanks! For posterity's sake, I'll post an answer detailing my steps.
  • Selfish
    Selfish over 7 years
    Thank you! I hope here's a way to bypass billing =\
  • Tushar Sheth
    Tushar Sheth over 6 years
    I am getting error "TypeError: admin.storage is not a function"
  • corysimmons
    corysimmons over 6 years
    Tushar create an app w/o the security cert. Morgan, thanks. This is the correct answer. I'd add that .save() works for Buffers if you don't have the file locally (e.g. user needs to upload avatar or something).
  • gkiely
    gkiely over 6 years
    For anyone looking at getting the public url: bucket.file('image.jpg').getSignedUrl({ action: 'read', expires: '03-09-2491' }).then(results => { let url = results[0]; }); You can also find details here: stackoverflow.com/questions/42956250/… github.com/googleapis/nodejs-storage/blob/master/samples/…
  • Yasir
    Yasir over 6 years
    I am have a problem, this is working fine let bucket = admin.storage().bucket() but I have a folder in storage users/ and inside this folder I am storing images. How can I access this folder ??
  • Arsalan Khalid
    Arsalan Khalid about 6 years
    Thanks for the feedback, I find that I get 'firebase' has no exported member 'storage' with firebase.storage().ref()
  • ishandutta2007
    ishandutta2007 about 6 years
    both gcloud and google-cloud are depricated. @google-cloud/storage is the way to go
  • NonCreature0714
    NonCreature0714 over 5 years
    That is very interesting! In my case, my app was also deployed, so what’s interesting is this works for you but not me. My work around was using Google Cloud storage
  • Saccarab
    Saccarab over 5 years
    how do you authenticate a user and serve him his files during all this?
  • FabricioG
    FabricioG over 4 years
    How is this the right answer? It's not deprecated: firebase.google.com/docs/storage/web/start
  • NonCreature0714
    NonCreature0714 over 4 years
    If you're downvoting because this isn't a good answer for you... then please refer to the very first line in my answer, which redirects users to the correct answer. I'm keeping this answer here for posterity.
  • Ronen Rabinovici
    Ronen Rabinovici almost 4 years
    See this link for updated and available libs: firebase.google.com/docs/web/setup#expandable-8
  • Mike Miller
    Mike Miller almost 4 years
    The updated answer is also out of date, as "npm WARN deprecated [email protected]: The google-cloud package has been deprecated." But don't feel bad, it seems google's own document is even MORE out of date.
  • Mike Miller
    Mike Miller almost 4 years
    Google's documentation is wrong, I tried what they said and it doesn't work. The updated answer here does work.
  • Mike Miller
    Mike Miller almost 4 years
    Correction, the updated answer here does NOT work, it is deprecated too.
  • Peritract
    Peritract over 3 years
    This is the only option that worked for me and didn't add a huge amount of complexity.