Wednesday 19 April 2017

How to insert filename into MongoDB using Multer

I have a form in AngularJS with an input type file to upload just one image per submit. Using Node.js, Express, Mongoose and Multer, I'm trying to upload the image inside a specific directory (this part is working well) and insert its filename together with the other data of the form into a MongoDB collection (called workers).
The html code (just the input file):

<form novalidate name="formulario" class="row" ng-submit="submeter()">
    <label class="btn-bs-file btn btn-primary">
        Select Image
        <input type="file" ngf-select ng-model="worker.file" name="file" ngf-pattern="'image/*'" accept="image/*" ngf-max-size="20MB" file-model="myFile"/>
    </label>
    <label>Image Preview</label>
    <div class="imgArea">
        <img style="width:150px;" ngf-thumbnail="worker.file || '/imagens/thumb.png'" ng-model="worker.file"/>
    </div>
    <button type="submit" class="btn btn-primary" ng-disabled= "formulario.$invalid">
        Save
    </button>
</form>

mydirective.js (to avoid redirect to another page when submit):

.directive('fileModel', ['$parse', function ($parse) {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var model = $parse(attrs.fileModel);
            var modelSetter = model.assign;

            element.bind('change', function(){
                scope.$apply(function(){
                    modelSetter(scope, element[0].files[0]);
                });
            });
        }
    };
}]);

The worker-controller.js:

$scope.submeter = function() {

        if ($scope.formulario.$valid) {
            cadastroDeWorkers.cadastrar($scope.worker)
            .then(function(dados) {
                $scope.mensagem = dados.mensagem;
                if (dados.inclusao) $scope.worker = {};
            })
            .catch(function(erro) {
                $scope.mensagem = erro.mensagem;
            });
        }

        var file = $scope.myFile;
        var uploadUrl = "/upload";
        var fd = new FormData();
        fd.append('file', file);

        $http.post(uploadUrl,fd, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
        .success(function(){
            console.log("success!!");
        })
        .error(function(){
            console.log("error!!");
        });
    };

The express.js (and my tries to insert filename data into Mongo):

var express = require('express');
var app = express();
var consign = require('consign');
var bodyParser = require('body-parser');
var fs = require('fs');
var multer = require('multer');

app.use(function(req, res, next) { //allow cross origin requests
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET");
    res.header("Access-Control-Allow-Origin", "http://localhost");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

app.use(express.static('./public'));
app.use(bodyParser.json());

var storage = multer.diskStorage({ 
  destination: function (req, url, cb) {
      cb(null, './uploads/')
  },
  filename: function (req, url, cb) {
      var datetimestamp = Date.now();
      cb(null, url.fieldname + '-' + datetimestamp + '.' + url.originalname.split('.')[url.originalname.split('.').length -1]);
  }
});
var upload = multer({ //multer settings
    storage: storage
}).single('file');

/** API path that will upload the files */

app.post('/upload', function(req, res, next) {
    //from this point I tried to insert filename into MongoDB
    upload(req,res,function(err){
        if(err){
            res.json({error_code:1,err_desc:err});
            return;
        }
        res.json({error_code:0,err_desc:null});

        console.log(req.file);
        console.log('TEST: ' + req.file.filename);
        fs.readFile(req.file.path, function (err, data) {
            var newPath = "./uploads/" + req.file.filename;
            /*fs.writeFile(newPath, data, function (err) {
                res.send("hi");  
            });*/
            console.log(newPath);
        });

    });
});

module.exports = app;

And finally, the worker.js (the model):

var mongoose = require('mongoose');
var schema = mongoose.Schema({
    (other fields from form)...
    file: {
        data: Buffer, 
        contentType: String,
        required: false
    },
    ...
    //If I try to use just type: String on file model, it displays an error trying to insert the image in base64 format
});
mongoose.model('Worker', schema);

The result is: all the fields are inserted into the MongoDB (name, email, etc.), the image is uploaded into "uploads" directory, but the filename is not inserted in the "file" field into the Mongo, and I lose the image reference. What's wrong with my code?



via Atoyansk

No comments:

Post a Comment