NODEJS(3)File Upload Sample
Serving something useful
Handling POST Requests
Add a textarea in start request handler in requestHandlers.js:
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; '+
'charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post">'+
'<textarea name="text" rows="20" cols="60"></textarea>'+
'<input type="submit" value="Submit text" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
We can add listeners in request as follow:
request.addListener("data", function(chunk){
//called when a new chunk of data was received
});
request.addListener("end", function() {
//called when all chunks of data have been received
});
Put the data and end event callbacks in the server, collecting all POST data chunks in the data callback, and calling the router upon receiving the end event, while passing the collected data chunks on to the router, which in turn passes it on to the request handlers.
Changes in server.js
function onRequest(request, response) {
var postData = "";
…snip...
request.setEncoding("utf8");
request.addListener("data", function(postDataChunk){
postData += postDataChunk;
console.log("Received POST data chunk' " + postDataChunk + "'.");
});
request.addListener("end", function() {
route(handle, pathname, response, postData);
});
…snip...
We did three things in sever.js, we defined that we expect the encoding of the received data to be UTF-8.
We add an event listener for the "data" event which step by step fills our new postData variable whenever a new chunk of POST data arrives.
When all POST data is gathered, we will call the end event to pass the data to router.
We will change the router.js and display the content.
function route(handle, pathname, response, postData) {
…snip…
handle[pathname](response, postData);
…snip…
And in requestHandlers.js, we include the data in our response of the upload request handler:
function upload(response, postData) {
…snip…
response.write("You've sent: " + postData);
…snip…
We will use querystring module to parse the postData.
var querystring = require("query string");
…snip…
querystring.parse(postData).text
…snip…
Handling file uploads
how to use an external module. The name of the external module is node-formidable. We need to install other modules in NPM.
>npm install formidable
Then we can try to use this in requestHandlers.js
var fs = require("fs");
var formidable = require("formidable");
…snip…
function start(response) {
console.log("Request handler 'start' was called.");
var body = '<html>'+
'<head>'+
'<meta http-equiv="Content-Type" content="text/html; '+
'charset=UTF-8" />'+
'</head>'+
'<body>'+
'<form action="/upload" method="post" enctype="multipart/form-data">'+
'<input type="text" name="title" value="hello" /> <br/>'+
'<input type="file" name="upload" multiple="multiple">' +
'<input type="submit" value="Upload File" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
function upload(response, request) {
console.log("Request handler 'upload' was called.");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.parse(request, function(error, fields, files){
console.log("parsing done");
/* Possible error on windows system:
tried to rename to an already existing file */
fs.rename(files.upload.path, "/tmp/test.png", function(err) {
if(err){
fs.unlink("/tmp/test.png");
fs.rename(files.upload.path, "/tmp/test.png");
}
});
response.writeHead(200, {"Content-Type": "text/html"});
response.write("received image:<br />");
response.write(fields.title + "<br />");
response.write("<img src='/show' />");
response.end();
});
}
function show(response){
console.log("Request handler 'show' was called.");
fs.readFile("/tmp/test.png", "binary", function(error, file){
if(error){
response.writeHead(500, {"Content-Type": "text/plain"});
response.write(error + "\n");
response.end();
}else {
response.writeHead(200, {"Content-Type": "image/png"});
response.write(file,"binary");
response.end();
}
});
}
exports.show = show;
In other file, router.js, server.js, index.js, we will pass the parameter request like response. And we will add show handler to our requestHandlers
route(handle, pathname, response, request);
handle[pathname](response, request);
handle["/show"] = requestHandlers.show;
references:
http://www.nodebeginner.org/#serving-something-useful