'Multer not adding file extension

I'm working on a Node.js/MongoDB based website and i'm trying to upload images directly on server using Express, Jade, and Multer, but no matter what i do, i can't achive to upload the file with extension.

I've got this on my app.js file:

var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var multer = require('multer');

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, './uploads')
    },
    filename: function (req, file, cb) {
        cb(null, file.originalname)
    }
});

var upload = multer({ storage: storage });


var app = express();

mongoose.connect("mongodb://localhost/primera_pagina");

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(multer({dest: "./uploads"}).single("image_avatar"));


var productSchema = {
    title:String,
    description:String,
    imageURL:String,
    pricing:Number
};

var Product = mongoose.model("Product", productSchema);

app.set("view engine","jade");

app.use(express.static("public"));

app.get("/",function(req,res){

    res.render("index");

});

app.post("/productos",function(req,res){
    if(req.body.password == "123"){
        var data = {
            title: req.body.title,
            description: req.body.description,
            imageURL: "image_avatar",
            pricing: req.body.pricing
        }

        var product = new Product(data);

        console.log(req.file)

    }else{
        res.render("index");
    }


});

app.get("/productos/new",function(req,res){
    res.render("productos/new");
});


app.listen(8080);

Any idea? I've search on Internet and tried every single method to add file extension with multer, but none has worked.



Solution 1:[1]

Multer strips the file extension for both security and collision reasons. For a workaround, try this:

var path = require('path')
var multer = require('multer')
var mime = require('mime-types')

var storage = multer.diskStorage({
  destination: './uploads/',
  filename: function (req, file, cb) {
    crypto.pseudoRandomBytes(16, function (err, raw) {
      if (err) return cb(err)

      cb(null, raw.toString('hex') + mime.extension(file.mimetype))
    })
  }
})

var upload = multer({ storage: storage })

(from https://github.com/expressjs/multer/issues/170#issuecomment-123402678)

It assigns a random file name, but keeps the file extension in tact.


You should also be using the authorize field in multer, since it looks like you only want files when the user has the correct password. Do something like this:

var upload = multer({ storage: storage }, limits : { fileFilter: authorize }); 

function authorize(req, file, cb) {
    if (req.body.password == PASS) {
        cb(null, true); //accept
    } else { 
        cb(null, false); //reject
    }
}

This will only save the file to disk if the user has inputted the correct password.

Solution 2:[2]

You can pass the right parameters for Multer like this in order to save the file extension:

var multer = require('multer');
var path = require('path')

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + path.extname(file.originalname)) 
  }
})

var upload = multer({ storage: storage });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Sharhabeel Hamdan