什么是express?
基于 Node.js 平台,快速、开放、极简的 Web 开发框架
使用 Express 可以快速地搭建一个完整功能的网站。
npm install express //使用方法 下载框架
// 引入框架
var express = require("express");
// 创建网站对象
var app = express();
// 监听端口
app.listen(8080)
路由
路由决定了由谁(指定脚本)去响应客户端请求。
在HTTP请求中,我们可以通过路由提取出请求的URL以及GET/POST参数。
格式:
app.all('*', (req, res, next)=>{
next();
})
app.get('/*.html', (req, res)=>{
res.send('hello'); //发送HTTP响应,express 提供的方法,不会出现中文乱码
})
app.post(/^html$/, (req, res)=>{
res.send('hello');
})
获取GET及POST数据
服务器端接收GET数据:
app.get('/chk', (req, res)=>{
res.send(JSON.stringify(req.query));
})
服务器端接收POST数据:
// 获取post数据的依赖模块 // npm install body-parser 下载
var bodyParser = require('body-parser');
// 作用是让req对象具有body属性,这个属性保存的是post数据
app.use(bodyParser.urlencoded());
app.post('/chk', (req, res)=>{
res.end(JSON.stringify(req.body));
})
为了练习获取GET及POST数据,这里做了两个简单的登录和注册页面,
这里使用了Axios库,用 引入.
Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
axios的作用主要是用于向后台发起请求的,还有在请求中做更多是可控功能。
post.html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
</head>
<body>
POST 注册页面 <a href="/b">登录</a><br>
<form id="form1" method="post" action="/registry">
用户名:<input type="text" id="username" /><br>
密码:<input type="text" id="password1" /><br>
确认密码:<input type="text" id="password2" /><br>
<input type="submit" value="提交" />
</form>
<script>
form1.addEventListener('submit', function(e){
e.preventDefault(); // 阻止默认行为
// 检查数据是否合法
if( username.value == "" ){
alert("请输入用户名");
return false;
}
if( password1.value == "" ){
alert("请输入密码");
return false;
}
if( password1.value != password2.value ){
alert("密码不一致");
password2.focus();
return false;
}
// 发送给后端的post数据
//var data = {"username":username.value} // 后端发送post数据时,用对象的形式描述数据
var data = "username="+username.value+"&password="+password1.value; // 前端发送post数据时,用字符串的形式描述数据
// 发起请求
axios.post("/registry", data).then(res=>{
alert(res.data);
})
//return false; // form1.onsubmit 时,可以使用return false组织默认行为
})
</script>
</body>
</html>
get.html页面
!<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js"></script>
</head>
<body>
Get 登录页面 <br>
<a href="/a">注册</a><br>
用户名:<input type="text" id="username" /><br>
密码:<input type="text" id="password" /><br>
<input type="button" value="提交" id="btn" />
<script>
btn.onclick = function(){
if(username.value =="" || password == ""){
alert("请输入用户名和密码");
return;
}
axios.get("login?username="+username.value+"&password="+password.value).then(res=>{
alert(res.data);
})
}
</script>
</body>
</html>
以下是main.js文件中的代码,这里使用了Nodejs模块化开发,Nodejs中的每一个模块都会自动创建一个 module 对象,同时 module 对象下有一个叫 exports 的属性,可以将某个类的实例赋值给 module.exports,从而导出这个类的实例。
使用"require"引入get.js和post.js文件.
//登录页面
app.get("/b",(req,res,next)=>{
res.sendFile(__dirname+"/temp/get.html");
})
//注册页面
app.get("/a",(req,res,next)=>{
// 把指定的文件,当成响应内容,显示出来
// sendFile 必须使用绝对路径
//console.log(__dirname) 获取当前文件的绝对路径
res.sendFile(__dirname+"/temp/post.html");
})
require("./modules/get.js")(app,fs);//()中为传过去的参数
require("./modules/post.js")(app,fs);
以下为post.js文件
module.exports = function (app,fs) {
app.post("/registry",(req,res)=>{
// 接收表单内容
// console.log(req.body);
var {username,password} = req.body;
// 用户名和密码中不能有关键字|
if(username.indexOf("|")>-1 || password.indexOf("|")>-1){
res.send("用户名和密码中存在非法字符|");
return;
}
// 用户名不能重复
if(fs.readFileSync("./db.txt").toString().indexOf("|"+username+"|")>-1){
res.send("用户名重复");
return;
}
// 往db.txt中添加数据
var str = "|"+username +"|"+password +"|"+req.ip +"|"+new Date()+"\r\n";
fs.appendFileSync("./db.txt",str);
// 响应内容
res.send("注册成功");
})
}
get.js 文件,模块的定义 module.exports 通过"=" 赋值,可以是函数,对象,数组等,
函数运行,就会调用函数内的代码.
module.exports = function(app,fs){
//处理登录页面
app.get("/login",(req,res)=>{
//接受登录表单页面内容
//console.log( req.query );
var {username,password} = req.query;
// 检查提交过来的用户名和密码是否在数据库中存在,
//如果存在,表示登录成功
if(fs.readFileSync("./db.txt").toString().indexOf("|"+username+"|"+password+"|")>-1){
res.cookie("username",username,{maxAge:1000*60})
res.send("登录成功");
}else{
res.send("登录失败");
}
});
}
静态文件static
- 设置静态文件夹:
app.use(express.static('public'));
把public目录设置为静态目录,作用是,用户访问页面时,先从静态目录中读取,
如果静态目录中不存在该文件,则向下执行路由解析相关的代码。
app.use(express.static('public'));
- 作用:
发起请求后,先从静态文件夹中找相关资源,
如果文件存在,直接当响应返回;
如果文件不存在,则进入路由程序,执行相关代码。
文件上传muter
上传文件模块 multer 通过 npm install multer 命令下载multer模块,以下为上传文件的路由规则
// 上传文件模块
var multer = require('multer'); // npm install multer
// 配置上传规则
// dest 表示文件保存到哪个目录下
// single 表示这是一个单一的文件域,参数为表单中文件域的name
var upload = multer({"dest":"public/uploads/"}).single('img1');
// 上传文件的路由规则
app.post('/uploadfile', (req, res)=>{
// 先检查用户是否登录
if( req.cookies.username == undefined ){
res.send("用户先登录,后上传")
return;
}
// 如果用户登录成功,则保存上传的文件
upload(req, res, (err)=>{
//console.log( req.file )
// 只允许上传图片
var serverFilePath = req.file.path; // 文件保存到服务器后的文件路径
var a = req.file.originalname.split(".");
var ext = a[a.length-1].toLowerCase(); // 上传文件的扩展名
if( ["jpg","png","gif","bmp"].indexOf(ext)>-1 ){
// 允许保存的文件
//console.log('保存了图片')
fs.renameSync(serverFilePath, "public/uploads/"+req.file.originalname);
res.send("上传成功")
}else{
// 不允许保存的文件
//console.log('删除了图片')
fs.unlinkSync(serverFilePath);
res.send("上传失败,只允许上传图片类型的文件");
}
})
})
- 前端代码为:
<form action="/chk" method="post" enctype="multipart/form-data">
<input type="file" name="img1" />
<input type="submit" value="提交">
</form>
- 后端:
var multer = require('multer'); // npm install multer
var upload = multer({"dest":"uploads/"}).single('img1');
app.post('/chk', (req, res)=>{
upload(req, res, function (err) { });
});
会话跟踪技术cookie
cookie是保存在客户端端的,所以用户每次访问一个地址的时候(发起请求),会把客户端的cookie通过这个请求,带给服务器.
在 req 中获取cookie; req表示请求,服务器接收请求,客户端发起请求,请求中存在cookie,
在 res 中创建cookie;
// 服务器端创建cookie
app.get("/setcookie", (req, res)=>{
res.cookie('user', '张三', { maxAge: 60000}); // 当前时间的60秒后过期
res.send('cookie创建成功 <a href="/getcookie">查看</a>')
})
// 服务器端获取cookie
app.get("/getcookie", (req, res)=>{
//console.log( req.cookies )
//res.send("查看cookie:" + req.cookies.user);
res.send(req.cookies.username)
})
// 服务器端删除cookie
app.get("/removecookie", (req, res)=>{
res.cookie('username', '', { maxAge: -1});
res.send('删除成功')
})
- 引入:
var cookieParser = require('cookie-parser'); // npm i cookie-parser
app.use(cookieParser());
- 设置:
res.cookie('x', '你好', { maxAge: 60000}); // 当前时间的60秒后过期
res.cookie('y', '中文abc123', { expires: new Date(Date.now() + 60000)});
res.cookie('z1', '会话时间');
res.cookie('z2', '路径', { path: '/'});
- 获取:
console.log(req.cookies)
ejs模版
- ejs语法:
<%if ( 条件 ){ }else{ }%>
<%for ( var i=0; i<arr.length; i++ ){%>
<li><%=arr[i]%></li>
<%-'<li>转义'+arr[i]+'</li>'%>
<%}%>
<%- include b.ejs %>