Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which is the best way to store images for expressjs, mongodb site?

Tags:

I'm new express, nodejs, mongodb. I'm building a website for a clothing shop. They want to upload images frequently, maybe every 2 days they will upload new images, and those images need to be shown on the website quickly, thumbnails. Click on the image will show detail the product, etc.

My question is what are the best ways to store images?

  1. Store images into hard disk and just store the absolute path into database mongodb?
  2. Stored images as binary/base64 into database mongodb?

How to load images into the website quickly?

Thanks

like image 783
jack.pop Avatar asked May 03 '19 04:05

jack.pop


People also ask

What is the best way to store images in MongoDB?

You can store the images in the MongoDB database by creating a schema with Mongoose. The schema is defined by creating a file, model. js . The data type Buffer is used for storing the images in the database form of arrays.

Is it good practice to store image in MongoDB?

No, MongoDB is not a good place for storing files. If you want to store files, you should use storages like Amazon S3 or Google Could Storage. The good practice is to store the files in a storage and then to just save the URL of the uploaded image in the MongoDB.


2 Answers

Where do we store images?

Solution # 1 in MongoDB

So the first solution is to store the images inside of MongoDB. It can accommodate image files or any file type. So you can take a file and tie it to a record inside of MongoDB and save it directly to your database.

With this approach tying a description page of a particular article of clothing with its corresponding image becomes easy because you can embed this image directly into your the development of that page and your client would be happy with that approach because when the user retrieves a detailed description page of that article of clothing it comes with the image.

So thats one possible solution, just take the image and store directly into MongoDB.

However, I am going to suggest that this is a bad approach. The reason for that, you can tell your client if there is pushback is that they will usually pay for their Mongo instance in terms of the amount of storage that their Mongo copy uses.

So all the more storage they use up, they pay more money per month.

For example, the last time I checked the use of MLab, they were charging $15 per GB. So that's $15 out of your customers pocket for hosting 1GB worth of images.

For yet another e-commerce website, we are talking about 3GB easy which translates into 330 images more or less, equally $15 a month.

So if one of their project managers is uploading a new article of clothing once a day, we are talking about a tremendous cost very quickly.

So, personally I think that storing any kind of file type directly inside of MongoDB is really not an option because it will get very costly.

So that's just one possible solution.

Solution # 2 in HD attached to server

So let's look at a second solution that might be available to you. You might use a hard drive thats tied your Express server. So when this application gets deployed to some cloud environment like Heroku, Digital Ocean, Linode or AWS you usually get a hard drive associated with your application.

So maybe you take the images and place them inside the local hard drive. This approach is what the vast majority of online posts and articles will advocate for:

How to upload, display and save images using node.js and express

https://appdividend.com/2019/02/14/node-express-image-upload-and-resize-tutorial-example/

https://medium.com/@nitinpatel_20236/image-upload-via-nodejs-server-3fe7d3faa642

Just with the three I gathered above you have a pretty robust blueprint to get started with.

Every single one says take the file and save it to your local hard drive. In this particular article:

https://alligator.io/nodejs/uploading-files-multer-express/

they are showing this code:

const storage = multer.diskStorage({   destination: 'some-destination',   filename: function (req, file, callback) {     //..   } }); 

They are using the image upload library called multer which provides the diskStorage() engine for uploading images to disk.

So this is one approach that the development community at-large agrees with.

This is a good approach in the context of a one-to-one mapping.

The problems with this approach starts to arise when we have multiple machines.

An example of this is if you have multiple machines hosted on Digital Ocean or Linode where each environment is a separate instance.

If you have all your images stored in the accompanying hard drive and then you start to scale your server up, they would each have their own separate hard drive.

So you may have a request that comes in through a load balancer and the load balancer decides where to send the request to like the diagram below:

enter image description here

So the issue with the above architecture is if the image gets saved to one of the two hard drives and then later on a request comes in to access that same image, but imagine the request gets routed to the other Express server with a different hard drive where the image does not exist.

This is a problem that comes up when you start to use a service provider like Linode or Digital Ocean where you have a one-to-one mapping between server and hard drive.

It's a short term solution if that is all you need for now, but once that application starts to scale its going to be a problem.

Solution # 3 outside data store

This third solution is one I have used in the past with React with Node applications and Ruby on Rails applications as well. In fact, my Ruby on Rails portfolio website uses this solution and it sits on the Heroku platform.

So when the image gets uploaded, rather than the Express API trying to store the file locally like on its own hard drive, it will take the image and use an outside data store to hold all the different images from the app.

The one I use for my portfolio website and what I have used for Node with React applications has been Amazon S3, but there also exists Azure File Storage and Google Cloud Storage. These systems are made to hold a tremendous amount of data and they can be any type of file that you can possibly imagine. Not just images such as in your case, but video files, audio files, etcetera.

There is no cap to the amount of storage you can have with S3, but you don't have to use S3, but it is seen as an industry standard right now, but you can easily just as well use Azure and Google Cloud.

The benefit of this solution that I think your customer will appreciate, Amazon S3 charges you like two pennies per gigabyte per month for storage.

like image 86
Daniel Avatar answered Sep 28 '22 19:09

Daniel


I think option 1 is the best choice. However, I strongly suggest using a service like AWS S3 along with cloudfront: this will increase the image load speed and the storage cost is really low.

That said, you can store just the image link or key and then call the URL reference in the front end.

Links of interest:

  • uppy.io

  • uppy along with AWS S3

like image 26
ManBearPig Avatar answered Sep 28 '22 17:09

ManBearPig