Renaming an uploaded file using Multer doesn't work (Express.js)

30,356

Solution 1

The usage for Multer has changed.

Currently Multer constructor accepts only three options:

  1. dist/storage
  2. fileFilter
  3. limits

now rename, onFileUploadStart, onFileUploadComplete would not work.

however renaming can be done using DiskStorage

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, '/tmp/my-uploads')
    },
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now())
  }
})

var upload = multer({ storage: storage })

have a look at these links:

Solution 2

I know this post is dated. I want to contribute to those who may arrive later. Below is a full functional server script to handle multiple uploaded pictures with random saved pictures names and file extension.

var express = require("express");
var multer = require("multer");
var app = express();
var path = require("path");
var uuid = require("uuid");

// Allow cross origin resource sharing (CORS) within our application
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    next();
});

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploadedimages/')
  },
  filename: function (req, file, cb) {
    cb(null, uuid.v4() + path.extname(file.originalname));
  }
})

var upload = multer({ storage: storage })

// "files" should be the same name as what's coming from the field name on the client side.
app.post("/upload", upload.array("files", 12), function(req, res) {
    res.send(req.files);
    console.log("files = ", req.files);
});

var server = app.listen(3000, function() {
    console.log("Listening on port %s...", server.address().port);
});

Solution 3

try this way which i'm using

  var storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, 'uploads/')
    },
    filename: function (req, file, cb) {
      console.log(file);
      var fileObj = {
        "image/png": ".png",
        "image/jpeg": ".jpeg",
        "image/jpg": ".jpg"
      };
      if (fileObj[file.mimetype] == undefined) {
        cb(new Error("file format not valid"));
      } else {
        cb(null, file.fieldname + '-' + Date.now() + fileObj[file.mimetype])
      }
    }
  })

  var upload = multer({ storage: storage })

Solution 4

we give a random name to file with the help of date and appends the original file extension with help of file.mimetype

try console.log(file.mimetype) you will get the file name and extension separated by '/' then I split it to array and fetch the extension from it. Try the below code.

let storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads')
  },
  filename: function (req, file, cb) {
    let extArray = file.mimetype.split("/");
    let extension = extArray[extArray.length - 1];
    cb(null, file.fieldname + '-' + Date.now()+ '.' +extension)
  }
})
const upload = multer({ storage: storage })

Solution 5

File has structure like this:

{
"fieldname": "avatar",
"originalname": "somefile.pdf",
"encoding": "7bit",
"mimetype": "application/pdf",
"destination": "./uploads",
"filename": "36db44e11b83f4513188f649ff445a2f",
"path": "uploads\\36db44e11b83f4513188f649ff445a2f",
"size": 1277191

}

The next example saves file with it's original name an extension and not with the strange name like it is by default. (Instead of "file.originalname" you can save it as you want)

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, './uploads') //Destination folder
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname) //File name after saving
  }
})

var upload = multer({ storage: storage })
Share:
30,356
Vincent Montalieu
Author by

Vincent Montalieu

I study computer science at Polytech Nice-Sophia. I'm also a big fan of cinema and music.

Updated on July 10, 2022

Comments

  • Vincent Montalieu
    Vincent Montalieu almost 2 years

    I'm trying to upload a file from a HTML form using Express.js and Multer. I've managed to save the file to the desired location (a folder named uploads).

    However, I'd like to rename the file while uploading it because, by default, Multer gives it a strange name such as:

    5257ee6b035926ca99923297c224a1bb

    Might be a hexadecimal time stamp or so but I need a more explicit name in order to call a script on it later.

    I've followed the explanation found here but it doesn't do anything more than it used to: uploading the file with the hexa name.

    Also, the two events onFileUploadStart and onFileUploadComplete never seem to be triggered as I don't get anything logged in my console.

    I am using two separate files for the server and the routing:

    app.js

    /**
     * Dependencies
     */
    
    var express = require('express');
    var path = require('path');
    var logger = require('morgan');
    var cookieParser = require('cookie-parser');
    var bodyParser = require('body-parser');
    
    /**
     * Importation of routes
     */
    var routes = require('./routes/index');
    var recog = require('./routes/recog');
    
    /**
     * Express
     */
    var app = express();
    
    app.use(logger('dev'));
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({extended: false}));
    app.use(cookieParser());
    app.use(express.static(path.join(__dirname, 'public')));
    
    // pour contrer les erreurs de cross domain
    app.use(function (req, res, next) {
    
        // Website you wish to allow to connect
        res.setHeader('Access-Control-Allow-Origin', '*');
    
        // Request methods you wish to allow
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    
        // Request headers you wish to allow
        res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    
        // Set to true if you need the website to include cookies in the requests sent
        // to the API (e.g. in case you use sessions)
        res.setHeader('Access-Control-Allow-Credentials', true);
    
        // Pass to next layer of middleware
        next();
    });
    
    /**
     * Routes
     */
    app.use('/', routes);
    app.use('/recog', recog);
    
    module.exports = app;
    

    recog.js

    /**
     * Requirements
     */
    var express = require('express');
    var router = express.Router();
    var multer = require('multer');
    var uploads = multer({
        dest: 'uploads/',
        rename: function (fieldname, filename) {
            console.log("Rename...");
            return filename + Date.now();
        },
        onFileUploadStart: function () {
            console.log("Upload is starting...");
        },
        onFileUploadComplete: function () {
            console.log("File uploaded");
        }
    });
    
    /**
     * Upload d'une image
     */
    router.post('/upload', uploads.single('image'), function (req, res, next) {
        console.log("Front-end is calling");
        res.json({status: 'success', data: 'Fichier chargé.\nOrgane sélectionné : ' + req.body.organ});
    });
    
    module.exports = router;
    

    I have been digging around but I can't figure out what the problem is as I am quite new to Node.js and JavaScript in general.

    Thanks for your help guys!

  • Clijsters
    Clijsters about 6 years
    While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
  • Justin Taddei
    Justin Taddei almost 5 years
    destination can also simply be a string when a dynamic upload directory isn't needed. e.i. destination: "uploadedImages/" instead of destination: function (...