Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically changing destination folder name #39

Closed
kokujin opened this issue Jun 18, 2014 · 21 comments
Closed

Dynamically changing destination folder name #39

kokujin opened this issue Jun 18, 2014 · 21 comments
Labels

Comments

@kokujin
Copy link

kokujin commented Jun 18, 2014

Is it possible to dynamically change the destination folder name depending on the field name? I made a quick test which failed

app.use(multer({
  dest: './uploads/',
  rename: function (fieldname, filename) {
      if(fieldname == 'avatar_file'){
          return filename.replace(/\W+/g, '-').toLowerCase() + Date.now()
      } else {
          return 'avatars/' + filename.replace(/\W+/g, '-').toLowerCase() + Date.now()
      }
  }
}))

Thanks

@hacksparrow
Copy link
Member

You can't. However, you can move the file to other locations after the file is uploaded.

@Mindstormer619
Copy link

@kokujin If you are still interested, I managed to do this with this small addition:

"rename" : function (fieldname, filename, req, res) {
    return path.join(fieldname, "i" + req.params.user_id);
}

(Saves it like <defaultFolder>/<fieldName>/i564221sdd456.jpg. I added the "i" because some stuff might complain with filenames starting with numbers)

I got the idea after looking at multer's source code. It seems that it does a path.join() to get the full path using the destination folder and the uploaded filename. Adding this works for me.

Note that this might change in the future, breaking this code? @hacksparrow?

@Mindstormer619
Copy link

Actually is there a specific reason why fieldnames and filenames cannot be passed to changeDest()?

@LinusU
Copy link
Member

LinusU commented Jul 8, 2015

@Mindstormer619 I think that the problem with using fieldnames is that they might not be available when the file comes. Most browsers sends the fields and files in the order they are placed in the DOM. So if the field for the name is after the file input field, multer won't know about it when it's receiving the file.

@Mindstormer619
Copy link

Ohhh, interesting. So I'm taking it that the rename feature works after the file is done uploading?

@Mindstormer619
Copy link

Hmm, looking at the source it doesn't seem to be a problem to be including the field name as a param for the changeDest() function. I could be wrong about this. Can someone confirm?

@Mindstormer619
Copy link

@LinusU I'm fairly sure that multer is well aware of the fieldname before the file is uploaded, as can be referenced by file.fieldname within the onFileUploadStart function

@LinusU
Copy link
Member

LinusU commented Jul 9, 2015

@Mindstormer619 Ahh, I think I misunderstood. I thought the question was about renaming it to the value of another field. The fieldname is known to multer at that point, although not passed to the changeDest function.

Your workaround should work 👍

@Mindstormer619
Copy link

@LinusU My workaround does work 😛 . However I'm asking about it being added directly to the source. Sort of like changing changeDest(dest, req, res) to changeDest(dest, req, res, fieldname).

@LinusU
Copy link
Member

LinusU commented Jul 9, 2015

This will be fixed by #131, specifically by #126 and #123

@pommyk
Copy link

pommyk commented Dec 3, 2015

@Mindstormer619 : This does not seem to work for me, the upload occurs, but only to the default directory. Warning: nodejs noob.

var express = require('express');
var multer  = require('multer');
var fs = require('fs');
//var upload = multer({ dest: 'uploads/' });

var app = express();

app.use(express.static(__dirname + "/public"));

app.post('/profile', multer({
    dest: 'uploads/', rename: function(fieldname, filename, req, res){
        var newDestination = path.join(req.body.hdnUserName);
        return newDestination;
    }}).single('uploadedFile'), function (req, res, next) {
        res.end('over');
    });

app.listen(8080, function(e){console.log('Server is listening on port 8080')});

@LinusU
Copy link
Member

LinusU commented Dec 3, 2015

#188 would probably have helped here. Your problem is that rename should be sent to the storage, not multer.

Try this:

var express = require('express')
var multer  = require('multer')
var fs = require('fs')

var storage = multer.diskStorage({
  destination: 'uploads/',
  filename: function (req, file, cb) {
    cb(null, req.body.hdnUserName)
  }
})
var upload = multer({ storage: storage })
var app = express()

app.use(express.static(__dirname + "/public"))
app.post('/profile', upload.single('uploadedFile'), function (req, res, next) {
  res.end('over')
})

app.listen(8080, function () {
  console.log('Server is listening on port 8080')
})

@pommyk
Copy link

pommyk commented Dec 4, 2015

@LinusU: Thanks for bringing up #188. This helped me get what i wanted thanks!

@AndrewKralovec
Copy link

AndrewKralovec commented May 20, 2016

Why not just create a storage script that changes the directory dynamically ?
Example of code i use to achieve this .

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);
    }
}

@Maltemo
Copy link

Maltemo commented Mar 6, 2019

@AndrewKralovec answers should be in the README.md file as an example
I think it would help a lot of people and help them to spend less time searching for this functionnality

@codertapsu
Copy link

Why not just create a storage script that changes the directory dynamically ?
Example of code i use to achieve this .

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);
    }
}

Thx so much!
___Arigato!

@kancharla-sandeep
Copy link

kancharla-sandeep commented Apr 16, 2019

Why not just create a storage script that changes the directory dynamically ?
Example of code i use to achieve this .

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);

Can you explain me where to call this script

@AndrewKralovec
Copy link

@kancharla-sandeep , sure thing. Please excuses the code quality, this project was from college, and it was before i even knew what a promise was.

https://github.com/AndrewKralovec/Alpha-Learning/search?q=storage&unscoped_q=storage

@prabhud9468
Copy link

Dynamically changing destination folder name is done by using formidable and fs

var formidable = require('formidable');
var fs = require('fs');

var initial_path = "D:/Files/";
var path=""; //dynamically created path will be stored at runtime
new formidable.IncomingForm().parse(req)
.on('field', (name, field) => {
  //field is an value of dynamic creation folder name
    path = init_path+field+"/";
    console.log(path); //Dynamic path is going to create
    fs.mkdir(path, { recursive: true }, (err) => {
        if (err) throw err;
    });
})
.on('fileBegin',(name, file) => {
    console.log(file.name);
    var a = file.name;
    var b = a.split('.');
    var fname = b[0].replace(/\s/g, '');
    file.path = path + fname+"."+b[1];
    file_path = file.path;
    savedImagePath = file_path.substring(1);
})
.on('file', (name, file) => {
    console.log('Uploaded ' + file.name);
})

@Akhilbmsb
Copy link

@prabhud9468 thanks for the solution, i was exactly looking for the similar kind of solution.

@Jean-Baptiste-Lasselle
Copy link

#188 would probably have helped here. Your problem is that rename should be sent to the storage, not multer.

Try this:

var express = require('express')
var multer  = require('multer')
var fs = require('fs')

var storage = multer.diskStorage({
  destination: 'uploads/',
  filename: function (req, file, cb) {
    cb(null, req.body.hdnUserName)
  }
})
var upload = multer({ storage: storage })
var app = express()

app.use(express.static(__dirname + "/public"))
app.post('/profile', upload.single('uploadedFile'), function (req, res, next) {
  res.end('over')
})

app.listen(8080, function () {
  console.log('Server is listening on port 8080')
})

Hi, I tried your snippet code, and well it does not even compile :

> myapp@0.0.1 build /home/scrapbook/tutorial/pokus
> tsc -p src

src/controllers/file.controller.ts(37,62): error TS2339: Property 'body' does not exist on type 'Request'.
  • my multer config :
    const pokusStorageOnDisk = multer.diskStorage({
      destination: function(req, file, cb) {
          // le répertoire [workspace/pokus] doit exister
          cb(null, 'workspace/pokus');
      },

      // By default, multer removes file extensions so let's add them back
      filename: function(req, file, cb) {
        console.log(" Valeur chopee : [" + file.fieldname + '-' + Date.now() + path.extname(file.originalname) + "]");
        console.log(" Valeur file.originalname : [" + file.originalname + "]");
        console.log(" Valeur file.path : [" + file.path + "]");
        console.log(" Valeur path.extname(file.originalname) : [" + path.extname(file.originalname) + "]");
        console.log(" Valeur req.body.hdnUserName : [" + req.body.hdnUserName + "]");
        cb(null, file.originalname);
      }
    });

So maybe your code compiled once.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests