21

How does one go about naming files parsed by Formidable in Node? Currently my files are saving as '7c9d182a9892bb7588b49ea9d364efd0.pdf', I would much prefer the original file names.

Anyone know how to do this?

6 Answers 6

27

This is how I did it (check out the .on(file'...) function):

// import required modules
    var express = require('express');
    var formidable = require("formidable"); // used for parsing form data
    var fs = require('fs');

// prevent bodyParser from handling multipart forms (ie only handle get and post requests)
    delete express.bodyParser.parse['multipart/form-data'];

// create server
    var app = express.createServer();

// connect middleware
    app.configure(function() {
        // creates body object on request object
            app.use(express.bodyParser());
            app.use(express.methodOverride());
        // used to display static files such as css
            app.use(express.static(__dirname + '/static'));
    });

// enable and define views
    app.set('views', __dirname + '/views');
    app.set('view engine', 'jade'); 

//******************************
//* create routes
//******************************

// file upload handling
    app.get('/photos/new', function(request, response) {
        response.render('photos/new');
    });
    app.post('/photos', function(request, response) {
        console.log('in /photos handler');
        var form = new formidable.IncomingForm();

        form.uploadDir = __dirname + '/static/upload/photos/';

        form.on('file', function(field, file) {
            //rename the incoming file to the file's name
                fs.rename(file.path, form.uploadDir + "/" + file.name);
        });

        form.on('error', function(err) {
            console.log("an error has occured with form upload");
            console.log(err);
            request.resume();
        });

        form.on('aborted', function(err) {
            console.log("user aborted upload");
        });

        form.on('end', function() {
            console.log('-> upload done');
        });

        form.parse(request, function() {
                response.render('photos/new');
        });
    });

// start our server
    app.listen(8888);
3
  • 1
    .on would give me errors. I got it to work, however, with form.on
    – user773737
    Commented Nov 13, 2013 at 20:14
  • 8
    Nowadays you have to pass an callback function to fs.rename: fs.rename(file.path, form.uploadDir + "/" + file.name, function( error ) {}); Commented Jun 25, 2018 at 23:28
  • Can you please elaborate how to do this @TorstenBarthel
    – florian
    Commented Aug 8, 2019 at 14:15
20

Here's my own answer:

form.uploadDir = "temp/uploads";
form.keepExtensions = true;

form
    .on('error', function(err) {
        throw err;
    })

    .on('field', function(field, value) {
        //receive form fields here
    })

    /* this is where the renaming happens */
    .on ('fileBegin', function(name, file){
            //rename the incoming file to the file's name
            file.path = form.uploadDir + "/" + file.name;
    })

    .on('file', function(field, file) {
        //On file received
    })

    .on('progress', function(bytesReceived, bytesExpected) {
        //self.emit('progess', bytesReceived, bytesExpected)

        var percent = (bytesReceived / bytesExpected * 100) | 0;
        process.stdout.write('Uploading: %' + percent + '\r');
    })

    .on('end', function() {


    });

form.parse(req);   

The answer was on the module's GitHub page all along!

1
  • why are you doing process.stdout.write() instead console.log()?
    – qodeninja
    Commented Sep 22, 2013 at 3:53
4

The easiest way is below (DEC 2022), No rename Nothing required.

app.post('/api/upload', (req, res) => {

    const form = formidable({
        multiples: true,
        encoding: 'utf-8',
        allowEmptyFiles: false,
        uploadDir: path.join(__dirname, "../my-app/src/uploads"),
       
        // Use it to control newFilename.              
        filename: (name, ext, part, form) => {
            return part.originalFilename; // Will be joined with options.uploadDir.
        }
    });

    form.parse(req, (err, fields, files) => {
        if (err) {
            res.status(400).json({ message: `${err}` })
        }
        console.log(files.myFile.filepath)
        console.log("sending file path")
        res.status(200).json(files.myFile.filepath);
    });
});

OUTPUT :

C:\Users\NAGESH\Desktop\web Dev\Formidable\my-app\src\uploads\Nagesh_Singh.pdf
1
  • 1
    Thank you! This works and is the simplest solution.
    – X33
    Commented Feb 14, 2023 at 2:52
1

you can get the original name from the formidable file object:

form.parse(req, function(err, fields, files) {
  var filename = files.upload.name;
});

hope this helps

1
  • Thanks. So would you you fs.rename from here? Is there a way for the form parser to do this? Commented Dec 9, 2011 at 2:33
1

Just wanted to add for future referance it looks like there has been a commit that adds the option:

var form = new formidable.IncomingForm();
form.keepFilenames = true;  

https://github.com/felixge/node-formidable/pull/488

although this does not look like it's reached a release yet on npmjs.org I'm sure it will as the commit has been approved.

1
  • 1
    If two requests come in at the same time, is there then a race condition for them to write to the same file name? Commented Feb 14, 2019 at 14:58
0

The other answers are a bit outdated, here is what worked for me as of May 2022.

const form = formidable({
  multiples: true,
  uploadDir: "/Users/yourname/Desktop/photos",
});

form.on("file", (field, file) => {
  fs.rename(
    file.filepath,
    form.uploadDir + "/" + file.originalFilename,
    () => {
      console.log(
        `Succesfully renamed to ${
          form.uploadDir + "/" + file.originalFilename
        }`
      );
    }
  );
});

Not the answer you're looking for? Browse other questions tagged or ask your own question.