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);
}
});
};