图书地址:《node入门》
实现文件上传功能
1、/start
页面实现图片上传,点击按钮跳转到/upload
。
2、/upload
页面处理图片,把图片重命名并重新放置到./tmp/test.png
,展示/show
。
3、/show
页面展示./tmp/test.png
有些代码注释是因为之前实现的是上传文字功能,且没有使用formidable插件,所以自己处理数据包。
后面的图片上传功能使用了插件。
1、入口文件index.js
,负责集合各个路径的handle
方法,并把集合后的对象传递给服务器。
var server = require('./server');
var router = require('./router');
var requestHandlers = require('./requestHandlers');
/*
每一个js文件对应一个路径的处理方法,通过模块引入后放到handle对象中
将需要用的handle对象与路由处理函数传给服务器启动模块
*/
var handle = {
'/': requestHandlers.start,
'/start': requestHandlers.start,
'/upload': requestHandlers.upload,
'/show': requestHandlers.show
};
server.start(router.route, handle);
2、创建一个服务器启动模块server.js
,把接收到的request
与需要返回的response
初始化,并传递给路由模块router.js
。
// server.js
var http = require('http');
var url = require('url');
/*
接收到路由处理方法route和handle处理方法
将接收到的request中的pathname传给路由处理方法route
将handle也传给route,使得route通过handle处理pathname
将接收到的response也传给route,交由handle来处理(非阻塞)
将整个request都传递给route,方便获取数据
*/
function start(route, handle){
function onRequest (request, response) {
// var postData = '';
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
// request.setEncoding("utf8");
//为了使整个过程非阻塞,Node.js会将POST数据拆分成很多小的数据块
// request.addListener("data", function (postDataChunk) {
// postData += postDataChunk;
// console.log("Received POST dara chunk '" + postDataChunk + "'.");
// })
// request.addListener('end', function () {
// route(handle, pathname, response, postData);
// })
route(handle, pathname, response, request);
}
http.createServer(onRequest).listen(8888);
console.log('Server has started!');
}
module.exports.start = start;
3、路由处理模块router.js
。
/*
接收到pathname和handle,判断在handle中是否有pathname的处理方法。
有的话就处理,没有的话就输出提示。
其他参数只是通过router传递给handle处理。
*/
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/plain"});
response.write("404 Not found");
response.end();
}
}
module.exports.route = route;
4、handle
处理方法模块requestHandlers.js
,其实应该是一个处理方法一个文件的,但是这个项目功能比较少,所以都放在一个文件里了。
var exec = require('child_process').exec; //执行shell命令
var querystring = require('querystring'),
fs = require('fs'),
formidable = require("formidable");
function sleep(milliSeconds){
var startTime = new Date().getTime();
while(new Date().getTime() < startTime + milliSeconds);
}
function start(response, request) {
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, request){
console.log("Request handler 'upload' was called.");
var form = new formidable.IncomingForm();
form.uploadDir='tmp';
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();
})
// response.writeHead(200, {
// "Content-Type": "text/plain",
//
// });
// response.write("You've sent: " + querystring.parse(postData).text);
// response.end();
}
function show(response, request) {
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();
}
})
}
module.exports.start = start;
module.exports.upload = upload;
module.exports.show = show;