MongoDB - GridFS : Utilisations pour stocker les images avec Node.js

02/01/2018
écrit par: ddtraceweb

 Nous souhaitons utiliser un système de stockage de fichiers adapté à de grosses volumétries afin de pouvoir les charger et les manipuler rapidement tout en gardant des informations utiles sur ceux-ci. Il existe un moyen avec MongoDB qui vous permettra de gérer correctement n'importe quel type de fichiers et nous allons l'utiliser pour stocker les images.

GridFS permet de stocker n'importe quel type de fichiers, video, audio, images, pdf, word... Il est adapté surtout également pour stocker de gros fichiers de grande tailles.

Les informations sont réparties en deux collections : fs.chunk (qui stocke sous format binaire le fichier) fs.files (qui stocke les informations sur le fichier, type mime, extension, metadata...).

Les deux documents ont le même ObjectId ce qui vous permet de trouver facilement les informations du fichier ou son binaire.

Voici  un exemple d'implémentation avec Node.js et Express pour uploader une image.

 

'use strict';
let fs = require('fs');
let Gridfs = require('gridfs-stream');
let multiparty = require('multiparty');
let mongoose = require('mongoose');
var im = require('imagemagick');
let mime = require('mime-types');

exports.uploadImage = function(req, res)
{
  let gfs = new Gridfs(mongoose.connection.db, mongoose.mongo); // on instancie l'objet GridFS
  let form = new multiparty.Form({maxFilesSize: 1024 * 1024 * 2});

  form.parse(req, function (err, fields, files) { //On parse les informations du formulaire

    if( mime.lookup(files.file[0].path) === 'image/png' ||
      mime.lookup(files.file[0].path) === 'image/jpeg' ||
      mime.lookup(files.file[0].path) === 'image/gif' ||
      mime.lookup(files.file[0].path) === 'image/pjpeg' ||
      mime.lookup(files.file[0].path) ==='image/x-png')
    {
      im.identify(files.file[0].path, function(err, features){

          if(err) console.log(err);

          if (!err) {

            let writestream = gfs.createWriteStream({
              filename: files.file[0].originalFilename,
              mode: 'w',
              content_type: mime.lookup(files.file[0].path),
               metadata: {
                 width : features.width,
                 height: features.height,
                 extension: files.file[0].originalFilename.split('.').pop()
              }
            });

            fs.createReadStream(files.file[0].path).pipe(writestream);

            writestream.on('close', function (file) {

              fs.unlink(files.file[0].path, function (err) {
                if (err) console.log(err);
                // handle error
                //console.log('success!');

                return res.send(file);
              });

            });
          }
        });

    }
    else {
      return res.status(400).send({err : 'err type file, only png, gif or jpeg, type : '
      + mime.lookup(files.file[0].path)});
    }

  });
};

 

Voici un exemple pour récupérer le contenu de l'image et l'afficher.


exports.getFile = function(req, res){
  'use strict';

  let gfs = new Gridfs(mongoose.connection.db, mongoose.mongo);

  _db.File.findOne({ _id: req.params['file_id'] }).exec( function(err, file) {
    if(err) console.log(err);
    if(file)
    {
      res.set('Content-Type', JSON.parse(JSON.stringify(file)).contentType);

      let readstream = gfs.createReadStream({
        _id: req.params['file_id']
      });

      //error handling, e.g. file does not exist
      readstream.on('error', function (err) {
        //console.log('An error occurred!', err);
        throw err;
      });

      readstream.pipe(res);
    }

  });
};