I am trying to add a file upload feature in my MEAN.js application. I made use of multer, but it places all the files directly in the destination specified at the time of initializing multer. I want to upload files to directories specific to the program for which they are being uploaded (of course create directory dynamically if it doesn't exist). Where should I specify the custom logic of creating directories on the fly and placing files in them.
3 Answers
I tried a lot of solutions but nothing helped me. Finally I wrote this and it works!
My solution (I am using express 4.13 and multer 1.2):
Imports:
var express = require('express');
var router = express.Router();
var fs = require('fs');
var multer = require('multer');
Storage variable (see documentation here)
var storage = multer.diskStorage({
destination: function (req, file, cb) {
var newDestination = 'uploads/' + req.params.__something;
var stat = null;
try {
stat = fs.statSync(newDestination);
} catch (err) {
fs.mkdirSync(newDestination);
}
if (stat && !stat.isDirectory()) {
throw new Error('Directory cannot be created because an inode of a different type exists at "' + dest + '"');
}
cb(null, newDestination);
}
});
Initializing Multer:
var upload = multer(
{
dest: 'uploads/',
limits: {
fieldNameSize: 100,
fileSize: 60000000
},
storage: storage
}
);
Using it!
router.use("/upload", upload.single("obj"));
router.post('/upload', controllers.upload_file);
Comments
You can't. However, you can move the file to other locations after the file is uploaded. That is probably your best bet. You could make your storage object a module and change the directory dynamically via init
var multer = require('multer'); // middleware for handling multipart/form-data,
// Constructor
module.exports = function (name) {
try {
// Configuring appropriate storage
var storage = multer.diskStorage({
// Absolute path
destination: function (req, file, callback) {
callback(null, './uploads/'+name);
},
// Match the field name in the request body
filename: function (req, file, callback) {
callback(null, file.fieldname + '-' + Date.now());
}
});
return storage;
} catch (ex) {
console.log("Error :\n"+ex);
}
}
I think the best solution to this problem is to use busboy, which let's you store your images in your desired location.
var Busboy = require('busboy');
var fs = require('fs');
app.post('.....',fucntion(req, res, next){
var busboy = new Busboy({ headers: req.headers });
busboy.on('field', function(fieldname, val) {
req.body[fieldname] = val;
});
busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
fstream = fs.createWriteStream("path/desiredImageName");
file.pipe(fstream);
fstream.on('close', function() {
file.resume();
});
})
return req.pipe(busboy);
})
2 Comments
nixxx
No no no! Multer uses busboy behind the scenes. Multer allows you to configure the file path where you want uploaded files to go!!! Example: var multer = require('multer'); var path = require('path') var storage = multer.diskStorage({ destination: function(req, file, cb) { cb(null, 'uploads/xml'); }, filename: function (req, file, cb) { cb(null, file.fieldname + '_' + Date.now() + path.extname(file.originalname)); } }); let upload = multer({ storage: storage });
Michael S
Jordy Cuan's answer is better