In this section, we will implement the user uploading the image and display the image in the browser.
The external module we want to use here is the node-formidable module developed by Felix Geisendörfer. It makes a good abstraction of parsing uploaded file data.
To install this external module, you need to execute the command under cmd:
The code copy is as follows:
npm install formidable
If you output similar information, it means that the installation has been successful:
The code copy is as follows:
npm info build Success: [email protected]
After the installation is successful, we can use request to introduce it:
The code copy is as follows:
var formidable = require("formidable");
What this module does here is to resolve the form submitted through HTTP POST request in Node.js. All we have to do is create a new IncomingForm, which is an abstract representation of the submitted form. After that, we can use it to parse the request object and get the required data fields in the form.
The image files in this case are stored in the /tmp folder.
Let’s first solve a problem: How can we display files saved on local hard drive in the browser?
We use the fs module to read the file to the server.
Let's add the /showURL request handler, which hardcodes the file /tmp/test.png content to the browser. Of course, you need to save the image to this location first.
Our team requestHandlers.js makes some modifications:
The code copy is as follows:
var querystring = require("querystring"),
fs = require("fs");
function start(response, postData) {
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">'+
'<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();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("You've sent the text: "+ querystring.parse(postData).text);
response.end();
}
function show(response, postData) {
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.start = start;
exports.upload = upload;
exports.show = show;
We also need to add this new request handler to the route map table in index.js:
The code copy is as follows:
var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");
var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;
server.start(router.route, handle);
After restarting the server, by visiting http://localhost:8888/show, you can see the picture saved in /tmp/test.png.
OK, in the end we want:
Add a file upload element in the /start form
Integrate node-formidable into our upload request handler to save uploaded images to /tmp/test.png
Embed the uploaded image into the HTML output from /uploadURL
The first item is simple. Just add a multipart/form-data encoding type in the HTML form, remove the previous text area, add a file upload component, and change the copy of the submit button to "Upload file". As shown in requestHandler.js as follows:
The code copy is as follows:
var querystring = require("querystring"),
fs = require("fs");
function start(response, postData) {
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" enctype="multipart/form-data" '+
'method="post">'+
'<input type="file" name="upload">'+
'<input type="submit" value="Upload file" />'+
'</form>'+
'</body>'+
'</html>';
response.writeHead(200, {"Content-Type": "text/html"});
response.write(body);
response.end();
}
function upload(response, postData) {
console.log("Request handler 'upload' was called.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("You've sent the text: "+ querystring.parse(postData).text);
response.end();
}
function show(response, postData) {
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.start = start;
exports.upload = upload;
exports.show = show;
Next, we need to complete the second step. We start with server.js - remove the processing of postData and request.setEncoding (this part of node-formidable will handle it itself), and instead pass the request object to the request route:
The code copy is as follows:
var http = require("http");
var url = require("url");
function start(route, handle) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(handle, pathname, response, request);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
Next, modify router.js, and this time you need to pass the request object:
The code copy is as follows:
function route(handle, pathname, response, request) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname](response, request);
} else {
console.log("No request handler found for " + pathname);
response.writeHead(404, {"Content-Type": "text/html"});
response.write("404 Not found");
response.end();
}
}
exports.route = route;
Now, the request object can be used in our upload request handler. node-formidable will handle saving the uploaded file to the local /tmp directory, and we need
What you want to do is make sure that the file is saved as /tmp/test.png.
Next, we put together the operations of processing file upload and renaming, as shown in requestHandlers.js:
The code copy is as follows:
var querystring = require("querystring"),
fs = require("fs"),
formidable = require("formidable");
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" enctype="multipart/form-data" '+
'method="post">'+
'<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");
fs.renameSync(files.upload.path, "/tmp/test.png");
response.writeHead(200, {"Content-Type": "text/html"});
response.write("received image:<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.start = start;
exports.upload = upload;
exports.show = show;
By doing this, our servers are all completed.
During the process of uploading images, some people may encounter such problems:
I guess the reason for this problem is caused by disk partition. To solve this problem, you need to change the default zero-time folder path of Formidable to ensure that it is on the same disk partition as the target directory.
We found the upload function of requestHandlers.js and made some modifications to it:
The code copy is as follows:
function upload(response, request) {
console.log("Request handler 'upload' was called.");
var form = new formidable.IncomingForm();
console.log("about to parse");
form.uploadDir = "tmp";
form.parse(request, function(error, fields, files) {
console.log("parsing done");
fs.renameSync(files.upload.path, "/tmp/test.png");
response.writeHead(200, {"Content-Type": "text/html"});
response.write("received image:<br/>");
response.write("<img src='/show' />");
response.end();
});
}
We added a sentence form.uploadDir = "tmp". Now restart the server and then perform the upload operation. The problem is perfectly solved.