Uploading files directly to MongoDB through a Simple VueJS App

Adarsh Tripathi
GDSC, IIIT Allahabad
9 min readMar 2, 2022

The problem of file upload directly to mongoDB wasn’t that much tricky but rather putting it all together. I found a lot of resources for individual parts of the problem, and thought it’d be good to put it all together and share what I learned. File upload with GridFS might be bit tricky but multer, gridfs-stream, multer-gridfs-storage makes it a lot easy 😀 to do, and we’ll see that as we proceed.

Our Objective

Our goal is to make a simple web app which can upload images to a MongoDB cloud and also to fetch the image data and display the same, we will be also writing the code for server side.

The Stack with which we will be dealing with is :

1.Node-js : We will be using nodeJs for serving our backend.

2. MongoDB Atlas: For storing our images we will be using mongoDB Atlas, which is a document-oriented NoSQL based database used for high volume storage. It uses collections and documents which consists of key-value pairs.

3. VueJs : We will be building the user-interface part with VueJs which is open-source front-end Javascript framework for building user interfaces.

You must have basic understading of Node-Js, npm package manager, Vue-js , MongoDB atlas to grab more from this article 😉.

Back-end

Step 1 : Setting up the project folder.

Create a project folder ( I have named my folder Vue-Mongo-file-upload you can name it as per your wish ) and navigate to the same and open the folder in VS Code. Run npm-init as usual we do to setup package.json in the project directory.

Image of VSCode terminal after running npm init
VS Code terminal after running npm init

Step 2: Installing Dependencies

We will be using express, body-parser, mongoose, cors, multer, multer-gridfs-storage, gridfs-stream, dotnev, nodemon.

Multer basically works as middleware for handling form-data used for uploading files. By using multer and multer-gridfs-storage we will upload and store the files directly to MongoDB. Gridfs-stream is a package which is used to stream files to and from MongoDB.

Run npm i "names of dependencies in terminal to install dependencies.

package.json after installing dependencies

Step 3 : Setting up server

To set up server, create index.js file since we specified the entry point of our node application during setting up package.json.

We need to import the libraries to our application and use them to initialize the app. Also set up port and code to listen to the request sent to the port. After implementation of these things the index.js file will look like :

index.js file after setting up server

Step 4: Configuring MongoDB and Creating Storage Engine

For writing image directly to MongoDB we will be using gridfs-stream.

For proceeding further one should have knowledge of setting up MongoDB Atlas and how to connect it with your application. If not you can refer to this tutorial.

You will get a connection string after setting up MongoDB atlas, copy that paste in a .env file in the same directory as index.js and type the database name and password in the connection string.

Since we have to deal with images so we have to create a storage engine which will only accept images and not file with other extensions. Here comes MIME type, which is a type of label used to identify a particular type of data. Just like file extensions does the work to identify the type of file on our devices, MIME type does that on internet. Here we will allow only image/jpeg and image/png. We will be uploading images to the collection uploads, which will be initialized as gfs.collection(‘uploads’) . After that in order to resolve the promise with the fileinfo, we have to pass the filename as Date-filename with original extension, the bucketName to be same as the collection name ‘uploads’ . We will create the variable upload and pass the storage engine in that as follows.

Step 5 : Making REST API endpoints.

We will be making 3 endpoints, one will be for uploading the image by using upload middleware which we have defined in previous step, second API will be getting information of all the images in the collection, which will be base API. In the third API, we will be creating readstream to read a single file so that we can display the image.

Below is the code for the upload route, we have used upload middleware to and since we have to upload a single file at a time so we have used upload.single. ‘file’ is actually the name of the file we will be uploading, and the same name we will be using the form tag in the front-end part. After the upload we will send the JSON data of the uploaded image as a response.

POST route for uploading a single image.

Now we can test this API on Postman or Insomnia. Fileinfo which we will get as response after sending post request is attached below :

fileinfo

NOTE : Multer will not process any type of form which is not multipart (multipart/form-data). Multer is basically used for uploading files, it is a node js middleware for handling multipart/form-data. So we must use enctype of our form as multipart/form-data. You can refer this link to learn more about multer.

GET All image files route :

Using the gfs stream which was initialized earlier we can get the array of all the images in the particular database using gfs.files.find().toArray(…) . After that we will check if any files exist or not, otherwise we will map through the array and check for the contentType/mimetype as per our wish and set the property isImage to be true, further we will send the files array as the response which will be an array containing information about each file.

GET Request for getting array of all the files in database.

For displaying the image we will have to use gridfs-stream using which we can create readstream to display a particular image. Using the stream initialized earlier we can get the single file by gfs.files.findOne({<query>}, …) , in our case, we will pass the query as filename. All the other code will be same as the base API. In addition we will have to write code for creating readstream after the check whether file is image or not. For creating readstream we will use gfs.createReadStream(options) , we will pass file.filname as options and then .pipe() readstream to the response.

ReadStream route for displaying a single image.

gridfs-stream is a node module which is used for streaming files to and from MongoDB, one thing is to note that the database must be opened before calling readstream or writestream. To know more about gridfs-stream you can refer this.

Now we are done with the back-end part. Now we will be making our client side. If you want to test these APIs before going on further you can test them on Postman or Insomnia.

Front-end

Step 1 : Setting up client folder

Install Vue-CLI using npm install -g @vue/cli and use vue create client command to create the client folder. Vue CLI( @vue/cli )is global npm package and provide vue command in the terminal. We can use CLI for various purpose like creating new project by vue create and also managing the project using graphical user interface via vue ui . Run vue create after installing @vue/cli in the Vue-Mongo-file-upload directory. We will use Vue-2 for our project.

You can refer the Vue-Js documentation for more details about Vue-CLI .

Now Navigate to client folder in your terminal and run npm run serve and go the domain http://localhost:portNumber(8080 in my case) in your browser to see the Client App running.

We will clear the App.vue and delete Helloworld.vue component and create our own components from scratch.

App.vue after cleaning up.

Step 2 : Making component for uploading images.

First change the name of the Web-app to Vue-js Image Upload , same can be done by changing title in the index.html file in public folder.

Now make a file ImageUpload.vue in the components folder. Import it in App.vue file.

App.vue after importing ImageUpload.vue

Now we have to make a simple UI just to test our APIs for the back-end, so we will not focus that much on the UI of our Web-App.

Simple UI for ImageUpload.vue component

Code for ImageUpload.vue component is :

Step 4 : Code for sending POST request for uploading image.

We will add @change event listener to input field which when changed call the function onFileSelected and assign the value of selectedFile to the file which is selected. After importing axios, we will create an async function onUpload to upload the formData to the desired API. We will be declaring functions inside the methods property. The onUpload function will be called when the form will be submitted, we will add an event listener @sumbit.prevent to the form.

ImageUpload.vue after creating methods for sending POST request

Step 5 : Creating methods for displaying images

We will be fetching data twice, from the base API. First, before the DOM is mounted by using created lifecycle hook, and second, after the image is uploaded, for which we have to use beforeUpdate lifecycle hook, here you can use any other lifecycle hook its up to you. We will declare imageData to store data of images after fetching it from the endpoint.

Lifecycle of a Vue Instance is a series of some steps that it goes through when initialized like being created then setting up data observation to the compiling template, mounting the instance to the DOM and finally updating the DOM when the data changes. They have some functions by default that run inside them as this process of initializing (creating and updating the DOM) the Vue instance goes on , these functions are called lifecycle hooks. If you are not familiar with lifecycle hooks then you can refer this.

For displaying image we will loop through the imageData as it will have the array of data of images. Here comes the role of the individual readStream API ( /files/:filename) which we created to display the image, src of the image will be http://localhost:4040/files/:filename in which filename will be accessed from imageData array.

ImageUpload.vue

This is the CSS for the imageContainer, you can design it as per your need.

Css for imageContainer

Now this completes the final part of our basic project. You can get the source code here .

😍 I hope you would have learned 💻 something from this article, don’t forget to leave a clap 👏.

About Me

Hello readers! Myself, Adarsh Tripathi. I am a novice Web Developer, currently pursuing B.Tech from IIIT-Allahabad.

Twitter : https://twitter.com/tripathi3adarsh

Github : https://github.com/rush-tea

--

--