http模块,url模块
var http=require('http');
var url=require('url');
http.createServer(function(req,res){
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
var str='<ul>';
for(i=1;i<=10;i++){
str+='<li>'+i+'</li>';
}
str+='</ul>';
res.write(str);
if(req.url.indexOf('favicon.ico') == -1){
var result=url.parse(req.url,true);
console.log('aid='+result.query.aid)
}
res.end();
}).listen(9999);
/*
调试流程:
写好页面之后cd到该文件目录,node server.js就能运行,但是每次修改都需要再次运行很麻烦,可以全局安装一个插
件,自动刷新
npm install -g supervisor
cd到文件目录 supervisor server.js
ctrl+c 停止进程
http模块
http模块node本身自带,利用createServer方法可以创建http服务器,带两个参数,req是请求参数,res是返回参数,
res.write写入内容,res.end()结束响应
每次浏览器访问会有两个请求一次是访问页面一次是获取favicon.ico图标,因此需要通过req中的url进行判断,如果
是后者则不打印信息,否则控制台会打印两次
url模块
url模块也是node自带,有三个方法:
url.parse(url,true) 可以把请求地址转化为对象,后面的true可以把query参数的内容转化为对象
url.format(urlObject) 与parse()正好相反,会把含有请求地址的对象转化为网址
url.resolve('http://www.baidu.com','news') 替换路径,输出 http://www.baidu.com/news
如果地址本身自带二级目录会被覆盖http://www.baidu.com/nav -> http://www.baidu.com/news
*/
自定义模块
//tools.js
var tools={
add:function(x,y){
return x+y;
},
sayHello:function(){
return '你好,nodejs';
}
};
// exports.tools=tools;
module.exports=tools;
//common1.js
var http=require('http');
var tools=require('./tools');
//如果foo.js不在根目录下会自动在node_modules文件夹下面找
var foo=require('foo');
//如果bar.js在node_modules下的bar文件夹下就需要bar/bar这样写,如果有package.json文件就可以省略
var bar=require('bar');
http.createServer(function(req,res){
res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});
res.write('你好,nodejs');
if(req.url.indexOf('favico') == -1){
var sum=tools.add(5,16);
console.log(sum)
console.log(bar.str)
}
res.end();
}).listen(9998);
/*
在commonjs规范下引入模块,自定义模块
通过require引入,根目录下使用./找到文件,不在根目录下的文件会自动从node_modules文件夹内寻找,
node_modules下面还有文件夹怎么办?cd到那个文件夹(本例是bar)
输入npm init --yes会自动生成一个package.json文件,里面的main是入口文件,有了这个json文件就不需要根据
目录找寻存放在node_modules下多级文件夹下的文件,require的时候直接把文件夹的名字写入就可以
暴露模块
exports foo=foo;使用的时候会多一层对象,例如tools.tools.add()
module.exports=foo;可以直接找到模块内的变量或者函数例如tools.add()
*/
fs模块--文件基本操作
var http=require('http');
var fs=require('fs');
http.createServer(function(req,res){
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
if(req.url.indexOf('favicon.ico') == -1){
fs.stat('html',function(err,stats){
if(err){
console.log(err)
}else{
console.log('文件:'+stats.isFile())
console.log('目录:'+stats.isDirectory())
}
})
fs.mkdir('css', function(err){
if(err){
console.log(err);
return false;
}
console.log('创建成功');
});
fs.writeFile('t.txt','你好,nodejs',function(err){
if(err){
console.log(err)
return;
}
console.log('写入成功')
});
fs.appendFile('t1.txt','不存在就创建\n', 'utf8', function(err){
if(err){
console.log(err)
return;
}
console.log('追加成功')
});
fs.readFile('html/index.html',function(err,data){
if(err){
console.log(err)
return;
}
console.log('读取成功')
console.log(data.toString())
});
fs.readdir('html',function(err,data){
if(err){
console.log(err)
return;
}
console.log('读取成功')
console.log(data)
});
fs.rename('html/index2.html', 'html/newsName.html', function(err){//改名 剪切
if(err){
console.log(err)
return;
}
console.log('改名成功')
});
fs.rename('html/newName.html', 'html2/newName.html', function(err){//改名 剪切
if(err){
console.log(err)
return;
}
console.log('剪切成功')
});
fs.rmdir('delmkdir', function(err){
if(err){
console.log(err)
return;
}
console.log('删除目录成功')
});
fs.unlink('remove.txt', function(err){
if(err){
console.log(err)
return;
}
console.log('删除文件成功')
});
//示例:判断upload文件夹是否存在,不存在就创建
fs.stat('upload',function(err,stu){
if(err){
fs.mkdir('upload',function(err2){
if(err2){
console.log(err2);
return false;
}
console.log('创建成功!');
});
}else{
console.log('目录已经存在!');
}
})
//示例:获取文件目录,并且打印出文件类型(文件or目录)
fs.readdir('html',function(err,data){
if(err){
console.log(err);
return;
}
//递归自执行函数
var str='<ul>';
var fileArr=[];//文件夹类型数组
var docArr=[];//文件类型数组
(function getFileType(nums){
if(nums >= data.length){
if(fileArr.length > 0){
for(i=0;i<fileArr.length;i++){
str+='<li style="color:red">[文件夹]'+fileArr[i]+'</li>';
}
}
if(docArr.length > 0){
for(i=0;i<docArr.length;i++){
str+='<li>[文件]'+docArr[i]+'</li>';
}
}
str+='</ul>';
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
res.write(str);
res.end();
return false;
}
fs.stat('html/'+data[nums],function(err,stau){
if(stau.isDirectory()){
fileArr.push(data[nums]);
}else{
docArr.push(data[nums]);
}
getFileType(nums+1);
});
})(0);
});
//fs.stat的操作类似下面的代码,会输出3个3
for(i=0;i<3;i++){
setTimeout(function(){
console.log(i)
},500)
}
}
res.end();
}).listen(9999);
/*
fs.stat(path, options, function(err,stau){});——检测是文件还是目录,异步操作
fs.mkdir(path, mode, function(err){});——创建目录
fs.writeFile(path, data, options, function(err){});——写入文件(会覆盖)
fs.appendFile(path, data, options, function(err){});——追加文件
fs.readFile(path, options, function(err,data){});——读取文件,通过toString()转换为字符串
fs.rmdir(path, function(err,data){});——读取目录
fs.rename(oldPath, newPath, function(err){});——重命名文件,剪切文件
fs.unlink(path, function(err){});——删除文件
在最后一个示例中因为fs.stat是异步操作,因此要使用自执行函数,把异步操作转换为同步操作,分为两种形式循环+自
执行函数和递归自执行函数,
需要注意的是在获取到目录后判断文件类型的时候要加上目录地址,否则会报错
*/
fs模块--文件流
var fs = require("fs");
var reradStream = fs.createReadStream('input.txt');
var writerStream = fs.createWriteStream('output.txt');
var data = '我是从数据库获取的数据,我要保存起来11\n';
// 读取文件流
var str='';
var count=0;
reradStream.on('data',function(chunk){
str+=chunk;
count++;
})
reradStream.on('end',function(chunk){
console.log(str)
console.log(count)
console.log('读取完成')
})
reradStream.on('error',function(error){
console.log(error)
})
// 写入文件流
for(var i=0;i<10;i++){
writerStream.write(data,'utf8');
}
//标记写入完成
writerStream.end();
writerStream.on('finish',function(){
console.log('写入完成111');
});
//失败
writerStream.on('error',function(){
console.log('写入失败');
});
// 管道
reradStream.pipe(writerStream);
/*
fs.createReadStream('fileName')创建文件流读取对象
用on接受广播:
data:分片读取;
end:读取结束
error:错误信息
fs.createWriteStream('fileName')创建文件流写入对象
.end():标记文件末尾
用on接受广播
finish:写入结束
error:写入错误
管道pipe()
reradStream.pipe(writerStream),读取后可直接写入
*/
创建一个静态WEB服务器
1、地址栏输入地址能够访问页面
2、css、js加载正确并起作用(设置其正确的content-type类型)
3、不存在的页面跳转到404页面
setMime.js
exports.setMime=function(extname){
switch (extname) {
case '.html':
return 'text/html'
break;
case '.css':
return 'text/css'
break;
case '.js':
return 'text/javascript'
break;
case '.jpg':
return 'image/jpg'
break;
case '.png':
return 'image/png'
break;
case '.gif':
return 'image/gif'
break;
}
}
server.js
var http = require('http');
var fs = require('fs');
var path = require('path');
var url = require('url');
var mime=require('./module/setMime');//自定义模块,根据文件类型返回mime类型
http.createServer(function(req, res) {
if(req.url.indexOf('favicon') != -1){
res.end();
return false;
}
var pathName=url.parse(req.url).pathname;///index.html?1123,使用url模块获取干净的地址路径
var extname=path.extname(pathName);//使用path模块获取访问页面的后缀类型
if(pathName == '/'){//默认跳转到index.html页面
pathName='/index.html';
}
// 根据地址路径读取文件
//readFIle是异步获取,readFileSync是同步获取
fs.readFile('static/'+pathName,function(err,data){
if(err){
// 文件不存在则跳转到404页面
fs.readFile('static/404.html',function(err404,data404){
if(err1){
console.log(err404);
return false;
}
// 状态码设置为404
res.writeHead(404,{"Content-Type":"text/html;charset=utf-8"});
res.write(data404);
res.end();
})
return false;
}
var mimeType=mime.setMime(extname);//获取每个请求的文件mime类型
res.writeHead(200,{"Content-Type":mimeType+";charset=utf-8"});
res.write(data);
res.end();
})
}).listen(8001);
ejs模板引擎
var http = require('http');
var url = require('url');
var ejs = require('ejs');
http.createServer(function(req, res) {
if(req.url.indexOf('favicon') != -1){
res.end();
return false;
}
var userName='来自后台的消息';
var list=['111','222','333','444'];
var htmlStr='<h3>我是标题</h3>';
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
var pathName=url.parse(req.url,true).pathname;///index.html?1123,使用url模块获取干净的地址路径
if(pathName == '/'){//默认跳转到index.html页面
ejs.renderFile('views/index.html',{msg:userName,list:list,htmlStr:htmlStr},function(err,data){
if(err){
console.log(err)
}
res.end(data);
})
}else if(pathName == '/register'){
var msg='这是一个注册页面!';
ejs.renderFile('views/register.html',{msg:msg},function(err,data){
res.end(data);
})
}
}).listen(8001);
/*
1、引入ejs模块
2、ejs.renderFile()读取模板并且传入参数
*/
//index.html页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>首页</title>
</head>
<body>
<h2>这是一个ejs模板22</h2>
<h2><%= msg%></h2>
<%- htmlStr %>
<br>
<ul>
<% for(var i=0;i<list.length;i++){%>
<li><%=list[i]%></li>
<% } %>
</ul>
</body>
</html>
路由 get post
var http = require('http');
var url = require('url');
var ejs = require('ejs');
var fs = require('fs');
http.createServer(function(req, res) {
if(req.url.indexOf('favicon') != -1){
res.end();
return false;
}
var methodType=req.method.toLowerCase();//获取传值类型,get或者是post
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
var pathName=url.parse(req.url,true).pathname;///index.html?1123,使用url模块获取干净的地址路径
if(pathName == '/'){//默认跳转到login.html页面
ejs.renderFile('views/login.html',{},function(err,data){
if(err){
console.log(err)
}
res.end(data);
})
}else if(pathName == '/dologin' && methodType=='post'){
var postStr='';
req.on('data',function(chunk){
postStr+=chunk;
})
req.on('end',function(chunk){
console.log(postStr)
fs.appendFile('login.txt',postStr+'\n',function(err,data){
if(err){
console.log(err);
return;
}
console.log('写入成功')
});
res.end('<script>alert("登陆成功");history.back();</script>')
})
}else if(pathName == '/dologin'){
var info=url.parse(req.url,true);
info=JSON.parse(JSON.stringify(info));
ejs.renderFile('views/dologin.html',{query:info.query},function(err,data){
res.end(data);
})
}
}).listen(8001);
/*
1、post传值获取参数通过req.on(),类似流的方式,get传值通过url模块获取格式化之后的参数
2、路由使用urk模块,根据地址栏的pathname进行判断
*/
//login.html
<form id="dataForm" method="post" action='/dologin'>
<input placeholder='请输入账号' id='username' value='' name='username' autocomplete="off" maxlength="25">
<input type="password" placeholder='请输入密码' id='password' value='' name='password' autocomplete="off" maxlength="25">
<input type="submit" id ='btn' value="登录">
</form>
模块化路由封装
将web服务器中的req和res作为参数传递到封装的函数中,利用obj[属性]的方式访问方法
// index.js
var http = require('http');
var url = require('url');
var router = require('./module/router.js');
http.createServer(function(req, res) {
if(req.url.indexOf('favicon') != -1){
res.end();
return false;
}
res.writeHead(200,{"Content-Type":"text/html;charset=utf-8"});
var pathName=url.parse(req.url,true).pathname.replace('/','');
// 封装的路由函数
try {
router[pathName](req,res);
} catch(e) {
router['home'](req,res);
}
res.end();
}).listen(8001);
//router.js
var ejs = require('ejs');
var url = require('url');
var router={
home:function(req,res){
res.end('首页');
},
login:function(req,res){
ejs.renderFile('./views/login.html',{},function(err,data){
res.end(data);
})
},
dologin:function(req,res){
var info=url.parse(req.url,true);
info=JSON.parse(JSON.stringify(info));
ejs.renderFile('./views/dologin.html',{query:info.query},function(err,data){
res.end(data);
})
}
}
module.exports=router;
仿express路由封装
var http=require('http');
var url=require('url');
var G={};
//定义方法开始结束
var app=function(req,res){
var pathname=url.parse(req.url).pathname;
if(!pathname.endsWith('/')){
pathname=pathname+'/';
}
if(G[pathname]){
G[pathname](req,res); /*执行注册的方法*/
}else{
res.end('no router');
}
}
//定义一个get方法。功能:注册方法
app.get=function(string,callback){
if(!string.endsWith('/')){
string=string+'/';
}
if(!string.startsWith('/')){
string='/'+string;
}
//路径格式修改为:'/login/'
G[string]=callback;
}
//只有有请求 就会触发app这个方法
http.createServer(app).listen(3000);
//注册login这个路由(方法)
app.get('login',function(req,res){
console.log('login');
res.end('login');
})
app.get('register',function(req,res){
console.log('register');
res.end('register');
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。