Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse form value with formidable to filename

I´m using formidable to handle my file uploads in NodeJs. I´m a little stuck at parsing field values.

How do I get the value of project_id to the form handler, so I can write the parameter in my filename?

<input type="text" id="project_id" value="{{projects._id}}" readonly>

EDIT

To be more specific, here´s a detailed view of my form-upload handling:

app.post('/uploads/', function (req, res){
    var form = new formidable.IncomingForm();
    form.parse(req, function (err, fields, files) {
        res.writeHead(200, {'content-type': 'image/jpeg'});
        res.write('received upload: \n\n');
        var project = fields.project_id;
        res.end(util.inspect(project, {fields: fields, files: files}));
    });

    form.on('end', function(project, fields, files){ 
        console.log(project); 
        /*Temporary location of our uploaded file */
        var temp_path = this.openedFiles[0].path;
        /*The file name of the uploaded file */
        var file_name =  project + '.' + this.openedFiles[0].name;

I can log the var project in the form.parse part. But I don´t get the variable in the form.on('end'... part.

HTML form

<form   id="uploadForm"
    enctype="multipart/form-data"
    action="/uploads/"
    method="post">
    <input type="text" name="project_id" id="project_id" value="{{projects._id}}" readonly>
    <input multiple="multiple" type="file" name="upload" />
    <button type="submit">Upload</button>
</form>
like image 356
Wandkleister Avatar asked May 08 '15 16:05

Wandkleister


2 Answers

Formidable's end callback doesn't take any parameters, but I'm not sure you even need to call it if you're using the parse callback. I think what you're looking for is something like this:

var fs = require('fs');
app.post('/uploads', function(req, res, next) {
    var form = new formidable.IncomingForm();
    form.parse(req, function(err, fields, files) {
        if (err) next(err);

        // TODO: make sure my_file and project_id exist    
        fs.rename(files.my_file.path, fields.project_id, function(err) {
            if (err) next(err);
            res.end();
        });
    });
});

You would need to listen for the end() event if you chose not to use the parse callback, like this:

new formidable.IncomingForm().parse(req)
    .on('file', function(name, file) {
        console.log('Got file:', name);
    })
    .on('field', function(name, field) {
        console.log('Got a field:', name);
    })
    .on('error', function(err) {
        next(err);
    })
    .on('end', function() {
        res.end();
    });
like image 182
Andrew Lavers Avatar answered Nov 10 '22 04:11

Andrew Lavers


Client side script:

    //Upload the file
    var fd = new FormData();
    //Take the first selected file
    fd.append("dbDocPath", 'invoices/' + file.name);
    fd.append("file", file);
    $http({
            method: 'POST',
            url: $rootScope.apiUrl + 'uploadDocToServer',
            data: fd,
            headers: {
                'Content-Type': undefined
            },
            //prevents serializing payload.  don't do it.
            transformRequest: angular.identity,
        }).success(function (response) {
           if (response.success) {
           }
   })

Server side script:

var fileDir = path.join(__dirname, '/../uploads');

// create an incoming form object
var form = new formidable.IncomingForm();
var dbDocPath = '';
form.parse(req)
        .on('field', function (name, field) {
            //console.log('Got a field:', field);
            //console.log('Got a field name:', name);
            dbDocPath = field;
        })
        .on('file', function (name, file) {
            //console.log('Got file:', name);

            // specify that we want to allow the user to upload multiple files in a single request
            //form.multiples = true;

            // store all uploads in the /uploads directory
            form.uploadDir = fileDir;

            fs.rename(file.path, path.join(form.uploadDir, file.name));

            // every time a file has been uploaded successfully,
            // rename it to it's orignal name

            var bucket = new AWS.S3();
            //console.log(dbDocPath);

            var params = {
                Bucket: DocsConfig.bucketName,
                Key: dbDocPath,
                Body: fs.createReadStream(path.join(form.uploadDir, file.name)),
                ACL: 'public-read'
            };

            bucket.putObject(params, function (perr, pres) {
                if (perr) {
                    //console.log("Error uploading data: ", perr);
                } else {
                    fs.unlinkSync(path.join(form.uploadDir, file.name));
                    //console.log("Successfully uploaded data", pres);
                }
            });
        })
        .on('error', function (err) {
            res.send({'success': false, error: err});
        })
        .on('end', function () {
            res.send({'success': true});
        });
// parse the incoming request containing the form data
//form.parse(req);

Just keep one thing in mind that the sequence of sending parameters to formData() should be same as mentioned in above code as file upload needs path to upload to the destiny.

like image 36
Rahul Mankar Avatar answered Nov 10 '22 04:11

Rahul Mankar