Ionică Bizău Ionică Bizău - 2 months ago 283
Javascript Question

Upload files to Firebase storage using Node.js

I'm trying to understand how to upload files in Firebase Storage, using Node.js. My first try was to use the

firebase
library:

"use strict";

var firebase = require('firebase');

var config = {
apiKey: "AIz...kBY",
authDomain: "em....firebaseapp.com",
databaseURL: "https://em....firebaseio.com",
storageBucket: "em....appspot.com",
messagingSenderId: "95...6"
};

firebase.initializeApp(config);

// Error: firebase.storage is undefined, so not a function
var storageRef = firebase.storage().ref();

var uploadTask = storageRef.child('images/octofez.png').put(file);

// Register three observers:
// 1. 'state_changed' observer, called any time the state changes
// 2. Error observer, called on failure
// 3. Completion observer, called on successful completion
uploadTask.on('state_changed', function(snapshot){
...
}, function(error) {
console.error("Something nasty happened", error);
}, function() {
var downloadURL = uploadTask.snapshot.downloadURL;
console.log("Done. Enjoy.", downloadURL);
});


But it turns out that
firebase
cannot upload files from the server side, as it clearly states in the docs:


Firebase Storage is not included in the server side Firebase npm
module. Instead, you can use the gcloud Node.js client.

$ npm install --save gcloud


In your code, you can access your Storage
bucket using:

var gcloud = require('gcloud')({ ... }); var gcs = gcloud.storage();
var bucket = gcs.bucket('<your-firebase-storage-bucket>');



Can we use
gcloud
without having an account on Google Cloud Platform? How?

If not, how come that uploading files to Firebase Storage from the client side is possible?

Can't we just create a library that makes the same requests from the server side?

How is Firebase Storage connected with Google Cloud Platform at all? Why
firebase
allows us to upload images only from the client side?




My second try was to use the
gcloud
library, like mentioned in the docs:

var gcloud = require("gcloud");

// The following environment variables are set by app.yaml when running on GAE,
// but will need to be manually set when running locally.
// The storage client is used to communicate with Google Cloud Storage
var storage = gcloud.storage({
projectId: "em...",
keyFilename: 'auth.json'
});

storage.createBucket('octocats', function(err, bucket) {

// Error: 403, accountDisabled
// The account for the specified project has been disabled.

// Create a new blob in the bucket and upload the file data.
var blob = bucket.file("octofez.png");
var blobStream = blob.createWriteStream();

blobStream.on('error', function (err) {
console.error(err);
});

blobStream.on('finish', function () {
var publicUrl = `https://storage.googleapis.com/${bucket.name}/${blob.name}`;
console.log(publicUrl);
});

fs.createReadStream("octofez.png").pipe(blobStream);
});

Answer

When using the firebase library on a server you would typically authorize using a service account as this will give you admin access to the Realtime database for instance. You can use the same Service Account's credentials file to authorize gcloud.

By the way: A Firebase project is essentially also a Google Cloud Platform project, you can access your Firebase project on both https://console.firebase.google.com and https://console.cloud.google.com and https://console.developers.google.com You can see your Project ID on the Firebase Console > Project Settings or in the Cloud Console Dashboard

When using the gcloud SDK make sure that you use the (already existing) same bucket that Firebase Storage is using. You can find the bucket name in the Firebase web config object or in the Firebase Storage tab. Basically your code should start like this:

var gcloud = require("gcloud");

var storage = gcloud.storage({
  projectId: "<projectID>",
  keyFilename: 'auth.json'
});

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

...