'How do I use google cloud storage as a bucket to store user/client images in a MERN Stack app?

I'm working on a pretty vanilla boilerplate blog-style application using mongoDB, express, react and node. It allows for user registration, authentication, for authorized users to CRUD posts, make comments, and reply to comments (so far).

I have a well defined schema (using mongoose) and the User model has an avatar field which is supposed to be the URI for the profile picture for that user. That is what I'm now stuck at: integrating image hosting on Google Cloud Storage for the profile picture that the user uploads and then fetching the URL and saving it to user.avatar.

I've tried looking this up extensively but I really can't find a reliable solution to this. I should probably mention that this is the first time I'm working with file uploads (I'm a student, though this isn't a homework question).

Honestly, any kind of help would be much appreciated.

Edit: I have tried going through the docs for Google Cloud Storage.



Solution 1:[1]

https://cloud.google.com/nodejs/getting-started/using-cloud-storage has some good information, in Upload to Cloud Storage section.

function sendUploadToGCS (req, res, next) {
  if (!req.file) {
    return next();
  }

  const gcsname = Date.now() + req.file.originalname;
  const file = bucket.file(gcsname);

  const stream = file.createWriteStream({
    metadata: {
      contentType: req.file.mimetype
    },
    resumable: false
  });

  stream.on('error', (err) => {
    req.file.cloudStorageError = err;
    next(err);
  });

  stream.on('finish', () => {
    req.file.cloudStorageObject = gcsname;
    file.makePublic().then(() => {
      req.file.cloudStoragePublicUrl = getPublicUrl(gcsname); // this will be the URL you will use in your web pages
      next();
    });
  });

  stream.end(req.file.buffer);
}

Example also uses Multer which is a middleware for Express, for handling file uploads

Solution 2:[2]

Depending where you want the processing to happen, either in the frontend with React or in the backend with Express, you can use the Google Cloud Client library to upload the files to GCS and then either use Signed URLs or the Link URL that you can find inside the Object details in GCS and place it inside a <img src=... /> tag.

For instance, with the help of this documentation you can upload files like such:

/utilities/utils.js

const { Storage } = require('@google-cloud/storage');
const storage = new Storage();

export const uploadObject = async (bucketName, fileName) => {
  await storage.bucket(bucketName).upload(filename);
}

/routes/gcs.js

[...]
const { uploadObject } = require('../utilities/utils');

router.post('/api/uploadAvatar', async (req, res) => {
  await uploadObject(req.body.bucketName, req.body.fileName);
});

This example is specific to a case where you would do these kind of processes in the backend, but the concepts should apply the same if you decide to do it in the frontend.

For starters, I would recommend deciding early how you want to divide your React.js code and Express.js code. Do you want to employ a microservices-like architecture and have React call REST endpoints in the backend (server-side processing) for most tasks and keep client-side processing to a minimum? Or do you simply want to use your backend for communicating with mongodb and perform most processes in React? There are plenty of viable architectures out there and I invite you to lay out a meticulous plan beforehand!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Horatiu Jeflea
Solution 2