Node简单实现文件上传
项目目录结构
- index.js
- node_modules
- formidable
- requestHandler.js
- server.js
- tmp //文件上传目录
安装form表单解析模块formidable
npm install formidable
新建server.js,监听8888端口,开启http服务
var http = require("http");
var url = require("url");
function start(route, handle) {
http.createServer(function(request, response){
var pathname = url.parse(request.url).pathname;
console.log("Request for "+ pathname+ " received");
route(handle, pathname, response, request);
}).listen(8888);
console.log("Server has started.");
}
exports.start = start;
新建route.js,绑定路由到处理函数
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();
}
}
exports.route = route;
新建requestHandler.js,编码路由处理函数
var querystring = require("querystring"),
fs = require("fs"),
formidable = require("formidable");
//上传文件存储根路径
var rootDir = 'tmp';
var html = '';
//文件上传界面
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" multiple="multiple"><br/>'+
'<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.parse(request, function(error, fields, files){
console.log("parsing done");
fs.renameSync(files.upload.path, "tmp/"+files.upload.name);
response.writeHead(200, {"Content-Type": "text/html"});
response.write('<head> <meta http-equiv="Content-Type"
content="text/html;charset=UTF-8" /> </head>');
response.write("received file:<br/>");
walk(rootDir);
response.write(html);
html = '';
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();
}
});
}
//目录深度优先遍历
function walk(path){
var dirList = fs.readdirSync(path);
html += "<ul>"+path;
dirList.forEach(function(item){
if(fs.statSync(path + '/' + item).isDirectory()){
walk(path + '/' + item);
}else{
html += "<li><a href="+path+'/'+item+">"+item+"</a></li>";
}
});
html += "</ul>";
}
exports.start = start;
exports.upload = upload;
exports.show = show;
新建index.js,程序的入口,绑定路由到监听的http服务
var server = require("./server");
var route = require("./route");
var requestHandlers = require('./requestHandlers');
var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
handle["/show"] = requestHandlers.show;
server.start(route.route, handle);
另附:目录广度优先遍历
function walk(path){
var dirList = fs.readdirSync(path);
html += "<ul>"+path;
dirList.forEach(function(item){
if(fs.statSync(path + '/' + item).isFile()){
html += "<li><a href="+path+'/'+item+">"+item+"</a></li>";
}
});
dirList.forEach(function(item){
if(fs.statSync(path + '/' + item).isDirectory()){
walk(path + '/' + item);
}
});
html += "</ul>";
}
参考:
http://swordair.com/directory-traversal-in-nodejs/
http://www.nodebeginner.org/index-zh-cn.htm