Squighopper25 Squighopper25 - 28 days ago 12
Javascript Question

formidable.parse method not executing, nodejs and formidable package

Problem: .parse() method from node package 'formidable' doesn't want to execute.

Reasources: The code snippet on this site is what I was using for reference, if that helps: https://github.com/felixge/node-formidable

Description: I am trying to create a website which can upload and store a file with nodejs for the server side code. I am achieving this using httpdispatcher package for directing the user, and formidable package for processing an upload form.

I am encountering a problem where every time, my program executes as expected up until the formidable package method parse() and then stops doing anything. The browser tab sits attempting to reload, and after almost 5 minutes shows an error along the lines of 'server didn't send anything back'. I don't receive and errors from node.

Obviously, this code only sends the processed form data back to the user. I have just simplified it as far as I think is reasonable.

Code: nodejs, (server.js file):

var http = require('http');
console.log('http loaded');
var fs = require('fs');
console.log('fs loaded');
var dispatcher = require('httpdispatcher');
console.log('dispatcher loaded');

var formidable = require('formidable');
console.log('formidable loaded');
var util = require('util');
console.log('util loaded');

dispatcher.setStaticDirname('.');
dispatcher.setStatic('resources');
dispatcher.onGet('/main', function(request, response){
response.writeHead(200, {'Content-Type': 'text/html'});
fs.readFile('index.html', function(error, html){
response.end(html); //Callbacked to prevent async send of file read
})
});
dispatcher.onPost('/main', function(request, response){
console.log('upload url accessed');
processForm(request, response);
});

const PORT = 8000;

function processForm(request, response){
console.log('processForm launched');
var form = new formidable.IncomingForm();
console.log('formidable initailised');
form.parse(request, function(error, fields, files){
console.log('form parsing started');
response.writeHead(200, {'content-type': 'text/plain'});
console.log('head written');
response.write('data recieved:\n\n');
response.end(util.inspect({fields: fields, files: files}));
console.log('form passing ended');
});
}
function saveImage(){
console.log('saveImage called');
fs.readFile(request.files.uploadImage.path, function(error, imageData){
console.log('reading file');
path = './uploadedImages';
fs.writeFile(path, imageData, function(error){
console.log('fs encountered an error: %s', error);
});
});
console.log('saveImage ended');
}
function handleRequest(request, response){
console.log('request handler started');
console.log('request method: %s', request.method);
try{
console.log(`URL: %s was requested`, request.url);
dispatcher.dispatch(request, response);
}
catch(error){
console.log(`httpdispatcher encountered an error: %s`, error);
}
console.log('request handler ended');
}

var server = http.createServer(handleRequest);
server.listen(PORT, function(){
//Callback triggered when server is successfully listening.
console.log("Server listening on: http://localhost:%s", PORT);
});


Code: html, (index.html file):

<!DOCTYPE html>
<html>
<head></head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="uploadImage">
</form>
<form action="" enctype="multipart/form-data" method="post">
<fieldset>
<label for="imageTitle">Image title:</label>
<input type="text" id="imageTitle" name="imageTitle" placeholder="Enter title of image" />
<br />
<label for="imageDesription">Image desription:</label>
<textarea id="imageDesription" name="imageDesription" placeholder="Enter a description of the image"></textarea>
<br />
<input type="submit" value="Upload Image" />
</fieldset>
</form>
</body>
</html>


Thank you in advance.

Answer

Looks like httpdispatcher modifies request buffers so formidable can not extract the form values from it.

To test this, you can handle post request directly inside http module's callback, without dispatching the request:

function handleRequest(request, response){
    console.log('request handler started');
    console.log('request method: %s', request.method);

     // HERE
    if (request.method == 'POST') {
        processForm(request, response);
        return;
    }

    try{
        console.log(`URL: %s was requested`, request.url);
        dispatcher.dispatch(request, response);
    }
    catch(error){
        console.log(`httpdispatcher encountered an error: %s`, error);
    }
    console.log('request handler ended');
}

I would suggest you use express to dispatch the request based on method and route.

Comments