Light Flow
Light Flow

Reputation: 539

Node.js and Multer - Handle the destination of the uploaded file in callback function (req,res)

I'm new to Node.js and I ran into a simple problem lately.

I'm using multer module to upload images. In my web app all the users have a unique id, and I want the uploaded images to be stored in a directory to be named based on their id.

Example:

.public/uploads/3454367856437534

Here is a part of my routes.js file:

// load multer to handle image uploads
var multer  = require('multer');
var saveDir = multer({
  dest: './public/uploads/' + req.user._id, //error, we can not access this id from here
  onFileUploadStart: function (file) { 
  return utils.validateImage(file); //validates the image file type
  }
});

module.exports = function(app, passport) {

app.post('/', saveDir, function(req, res) {
                id     : req.user._id,  //here i can access the user id
    });
});

}

How can I access req.user._id attribute outside the callback function(req, res), so I can use it with multer, to generate the proper directory based on the id?

EDIT Here is what I have tried and didn't work:

module.exports = function(app, passport) {

app.post('/', function(req, res) {
    app.use(multer({
        dest: './public/uploads/' + req.user._id
    }));
});

}

Upvotes: 8

Views: 10589

Answers (4)

Arslan
Arslan

Reputation: 67

to dynamically create a directory from the req data, simply put the files at the end and other data at the top of your request ! multer will populate the text data by following this order and ensure you have access to the req data for dynamic directory creation.

enter image description here

Upvotes: 0

Sravan
Sravan

Reputation: 2019

You can accomplish this using multer to handle the dynamic creation of upload directory. The input parameter(for which you want to create a directory) should be called before sending a file name.

var express = require('express');
var app = express();
var multer = require('multer');
var fs = require('fs');
var mkdirp = require('mkdirp');
var bodyParser = require('body-parser');
app.use(bodyParser.json({limit: '5mb'}));
app.use( bodyParser.json() );       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
    extended: true,
    limit: '5mb'
}));

var storage =   multer.diskStorage({
    destination: function (req, file, callback) {
        var Id = req.body.id;
        upload_path = "./"+Id;
        mkdirp(upload_path, function (err) {
            if (err) console.error(err)
            else {
                console.log('Directory created');
                //setting destination.
                callback(null, upload_path);
            }
        });

    },
    filename: function (req, file, callback) {
        callback(null, file.orginalname)
    }
});
//multer setting and getting paramaters.
var upload = multer({ storage : storage }).single('upload_file');

//creating request for upload file
app.post('/uploadFile', function(req, res){
    res.set({ 'content-type': 'application/json; charset=utf-8' });
    res.header("Content-Type", "application/json; charset=utf-8");
    res.header("Access-Control-Allow-Origin", "*");
    res.charset = 'utf-8';
    //function upload_process(){
    upload(req, res, function(err){
        if(err){
            console.log('Error-->');
            console.log(err);
            res.json({"status": "Failure", "message":'There was a problem uploading your files.'+err});
            return;
        }
        else{
            console.log("fieldname"+req.files.length);
            if( req.files.length != 0){
                res.json({"status" : "Success", "message":'Your files are uploaded.'});
                console.log('File uploaded!');
            }
            else{
                console.log("No file uploaded. Ensure file is uploaded.");
                res.json({"status" : "Failure", "message" : 'No file uploaded. Ensure file is uploaded.'});

            }
        }
    });

});

});

Hope this helps! Happy coding

Upvotes: 0

Sridhar
Sridhar

Reputation: 11816

Update

Quite a few things have changed since I posted the original answer.

With multer 1.2.1.

  1. You need to use DiskStorage to specify where & how of the stored file.
  2. By default, multer will use the operating system's default directory. In our case, since we are particular about the location. We need to ensure that the folder exists before we could save the file over there.

Note: You are responsible for creating the directory when providing destination as a function.

More here

'use strict';

let multer = require('multer');
let fs = require('fs-extra');

let upload = multer({
  storage: multer.diskStorage({
    destination: (req, file, callback) => {
      let userId = req.user._id;
      let path = `./public/uploads//${userId}`;
      fs.mkdirsSync(path);
      callback(null, path);
    },
    filename: (req, file, callback) => {
      //originalname is the uploaded file's name with extn
      callback(null, file.originalname);
    }
  })
});

app.post('/', upload.single('file'), (req, res) => {
  res.status(200).send();
});

fs-extra for creating directory, just in case it doesn't exists

Original answer

You can use changeDest

Function to rename the directory in which to place uploaded files.

It is available from v0.1.8

app.post('/', multer({
dest: './public/uploads/',
changeDest: function(dest, req, res) {
    var newDestination = dest + req.user._id;
    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 + '"');
    }
    return newDestination
}
}), function(req, res) {
     //set your response
});

Upvotes: 9

negalis
negalis

Reputation: 1

you can solve this just referring to the input name and rename the path before assigning it.

app.use(multer({ dest: './standard_folder/',
    rename: function (fieldname, filename) {

      var pathHelper ='';
      if(fieldname =='otherKindOfFolderNeeded'){
        pathHelper = '../../path/to/other/folder/';
      }
      return pathHelper+uuid.v4()+Date.now();
    },
    onFileUploadStart: function (file) {
      console.log(file.originalname + ' is starting ...')
    },
    onFileUploadComplete: function (file) {
      console.log(file.fieldname + ' uploaded to  ' + file.path)
      done=true;
    }
  })
);

Upvotes: 0

Related Questions