Search code examples
javascriptnode.jsfirebasestreamfirebase-storage

How to pipe a stream to upload a file from node to Firebase Cloud?


TLDR;

This question is about the firebase API, and me wondering if it has a createWriteStream sort of way, to which I can pipe a readStream to, in order to upload a file.

The Full Question

I simply want to upload an image from my Node server to my Firebase Cloud.
Now, there's two ways to go about it:

  • The easy way: loading the entire file to memory before starting to upload.
  • The complex way: which is also the performant way, and it is by using streams.

The easy way is... well, easy.
You just use firebase's uploadBytesResumable as shown here in their documentation.

import fs from 'fs';
import path from 'path';
import { initializeApp } from 'firebase/app';
import { getStorage } from 'firebase/storage';
import { ref, uploadBytesResumable } from 'firebase/storage';

const firebaseApp = initializeApp(firebaseConfig);
const storage = getStorage(firebaseApp);

async function uploadImage() {
    // Step 1: load the ENTIRE file to upload
    const filepath = path.resolve(dirname, 'my-image.jpg');
    const fileToUpload = fs.readFileSync(filepath);

    // Step 2: upload the entire file to Firebase Cloud
    const storageRef = ref(storage, `images/path/on/bucket/my-image.jpg`);
    await uploadBytesResumable(storageRef, fileToUpload);
}

What I want however is the second way, with using streams. But where I get stuck is at the pipe stage, as I don't know what I need to pass to it:

import fs from 'fs';
import path from 'path';
import { initializeApp } from 'firebase/app';
import { getStorage } from 'firebase/storage';
import { ref, uploadBytesResumable } from 'firebase/storage';

const firebaseApp = initializeApp(firebaseConfig);
const storage = getStorage(firebaseApp);

async function uploadImage() {
    // Step 1: load the file to upload in chunks/buffers
    const filepath = path.resolve(dirname, 'my-image.jpg');
    const myReadStream = fs.createReadStream(filepath);

    // Step 2: upload stream to Firebase Cloud
    myReadStream.pipe(???)
}

I couldn't find an example anywhere on how to accomplish that...
What do I need to pass to .pipe()?
Please help.


Solution

  • To pipe a stream to upload a file from a Node.js application to Firebase Cloud Storage, you can use the Firebase Admin SDK for Node.js. This SDK allows you to interact with Firebase services, including Firebase Cloud Storage.

    const admin = require('firebase-admin');
    const storage = admin.storage();
    const bucket = storage.bucket();
    
    const fileStream = fs.createReadStream(localFile);
    const uploadStream = bucket.file(remoteFile).createWriteStream({
      contentType: 'application/octet-stream', // Set the content type as needed
    });
    
    fileStream.pipe(uploadStream);
    

    You can listen to events like 'error' and 'finish' to handle errors and success events during the upload process.

    And don't forget to ensure that you handle the finalization of the Firebase Admin SDK correctly when your application exits.