Search code examples
node.jsmongodbmongoosemulter

uploading images in mlab


currently i am storing images which are uploaded by node rest server in local directory "/uploads" . this is continuously increasing my repo size . to avoid this , i want to store image files in mongoDB atlas or mlab just like service.

    const express = require("express");
    const router = express.Router();
    const mongoose = require("mongoose");
    const multer = require('multer');

    const storage = multer.diskStorage({
      destination: function(req, file, cb) {
        cb(null, './uploads/');
      },
       filename: function(req, file, cb) {
        cb(null, new Date().toISOString() + file.originalname);
      }
    });

    const fileFilter = (req, file, cb) => {
     // reject a file
     if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png')           
     {
      cb(null, true);
      } else {
        cb(null, false);
     }
    };

    const upload = multer({
      storage: storage,
      limits: {
        fileSize: 1024 * 1024 * 5
      },
      fileFilter: fileFilter
    });

Please do help me in this. Thanks in advance.


Solution

  • You can achieve this by using a mongoose Schema and the fs core module to encode the image and unlink the file from /uploads.

    I would start by creating a Mongoose Schema to set the model of all information you want to store pertaining to your uploaded file.

    I'm going to use base64 encoding for this example.

    uploadModel.js

    const mongoose = require('mongoose');
    const fs = require('fs');
    const Schema = mongoose.Schema;
    
    mongoose.set('useCreateIndex', true);
    
    let uploadSchema = new Schema({
        name: {
          type: String,
        },
        mimetype: {
          type: String,
        },
        size: {
          type: Number,
        },
        base64: {
          type: String,
        }
    })
    
    module.exports = mongoose.model('upload',uploadSchema);
    

    After setting up a model create a function to base64 encode and module.exports that as well.

    To encode your file, use fs.readFileSync(path_to_file, encode_type). After the file has been encoded and saved in a variable you can use fs.unlink(path_to_file) to delete the file out of your /uploads folder.

    uploadModel.js

    module.exports.base64_encode = function(file) {
      return new Promise((resolve, reject) => {
        if(file == undefined){
          reject('no file found');
        } else {
          let encodedData = fs.readFileSync(file, 'base64');
          fs.unlink(file);
          resolve(encodedData.toString('base64'));
        }
      })
    } 
    

    Now inside your route file require your model.

    route.js

    const Upload = require('path_to_uploadModel');
    
    router.post('/path_to_upload', upload.single('form_name_of_file'), (req, res) => {
      let img = req.file;
    
      let model = new Upload({
        name: img.originalname,
        size: img.size,
        mimetype: img.mimetype,
      })
    
    
      Upload.base64_encode(img.path)
        .then((base64) => {
          model['base64'] = base64;
          model.save((err)=> {
            if(err) throw err;
          });
        }
    })
    

    Hope this helps