二十一、Node.js Express 框架

二十一、Node.js Express 框架

Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用

使用 Express 可以快速地搭建一个完整功能的网站

Express 框架核心特性:

1、 可以设置中间件来响应 HTTP 请求

2、 定义了路由表用于执行不同的 HTTP 请求动作

3、 可以通过向模板传递参数来动态渲染 HTML 页面

安装 Express

1
$ npm install express --save

以上命令会将 Express 框架安装在当前目录的 node_modules 目录中

node_modules 目录下会自动创建 express 目录

其它依赖模块

Express 框架只能开发简单的网站,如果要开发一个功能齐全的网站还需要安装一下模块

1、 body-parser

1
Node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据

2、 cookie-parser

1
解析 Cookie 的工具。通过 req.cookies 可以取到传过来的 cookie,并把它们转成对象

3、 multer

1
2
3
4
Node.js 中间件,用于处理 enctype="multipart/form-data"(设置表单的MIME编码)的表单数据
$ npm install body-parser --save
$ npm install cookie-parser --save
$ npm install multer --save

安装完后,可以使用以下命令查看 express 的版本号

1
2
3
$ npm list express
~/curl_main/node
└── express@4.16.2

第一个 Express 框架应用

我们使用 Express 框架开发一个 WEB 服务输出 “Hello World”

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var express = require('express');
var app = express();

app.get('/', function (req, res) {

res.write('<h1>Hello World</h1>');
res.write('Hello World </p>');
res.end();
})

var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js 
应用范例,访问地址为 http://:::8080

在浏览器中访问 http://127.0.0.1:8080

请求和响应

Express 路由回调函数的参数: requestresponse 对象封装了请求和响应的数据

1
2
3
app.get('/', function (req, res) {
// ...
})

requestresponse 对象包含很多属性和方法

Request 对象

request 对象表示 HTTP 请求,包含了请求查询字符串,参数,内容,HTTP 头部等属性

属性描述
req.app当 callback 为外部文件时,用 req.app 访问 express 的实例
req.baseUrl获取路由当前安装的URL路径
req.body req.cookies获得「请求主体」/ Cookies
req.fresh req.stale判断请求是否还「新鲜」
req.hostname req.ip获取主机名和IP地址
req.originalUrl获取原始请求URL
req.params获取路由的parameters
req.path获取请求路径
req.protocol获取协议类型
req.query获取URL的查询参数串
req.route获取当前匹配的路由
req.subdomains获取子域名
req.accepts()检查可接受的请求的文档类型
req.acceptsCharsets req.acceptsEncodings req.acceptsLanguages返回指定字符集的第一个可接受字符编码
req.get()获取指定的HTTP请求头
req.is()判断请求头Content-Type的MIME类型

Response 对象

response 对象表示 HTTP 响应,即在接收到请求时向客户端发送的 HTTP 响应数据

属性描述
res.app同 req.app 一样
res.append()追加指定 HTTP 头
res.set()在 res.append() 后将重置之前设置的头
res.cookie(name,value [,option])设置 Cookie
res.clearCookie()清除 Cookie
res.download()传送指定路径的文件
res.get()返回指定的HTTP头
res.json()传送JSON响应
res.jsonp()传送JSONP响应
res.location()只设置响应的 Location HTTP 头,不设置状态码或者返回信息
res.redirect()设置响应的Location HTTP头,并且设置状态码302
res.send()传送HTTP响应
res.sendFile(path [,options] [,fn])传送指定路径的文件,会自动根据文件 extension 设定 Content-Type
res.set()设置 HTTP 头,传入 object 可以一次设置多个头
res.status()设置 HTTP 状态码
res.type()设置 Content-Type 的 MIME 类型

Express 路由

前面我们已经学习开发了 HTTP 请求的基本应用,而路由决定了由哪个脚本去响应客户端请求

在 HTTP 请求中,我们可以通过路由提取出请求的 URL 以及 GET/POST 参数

现在我们在 Hello World 基础上添加一些功能来处理更多类型的 HTTP 请求

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var express = require('express');
var app = express();

// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js
应用实例,访问地址为 http://:::8080

我们可以尝试访问 http://127.0.0.1:8080 不同的地址查看效果

1、 访问首页 http://127.0.0.1:8080

2、 访问 http://127.0.0.1:8080/user/list

3、 访问 http://127.0.0.1:8080/abcd

4、 访问 http://127.0.0.1:8080/abcdefg

静态文件

Express 内置的中间件 express.static 可以设置静态文件 ( 如:图片, CSS, JavaScript 等)

我们可以将静态文件 ( 图片, CSS, JavaScript ) 等放到 static 目录下,然后使用 express.static 中间件来设置静态文件路径

1
app.use(express.static('static'));

我们可以放一些图片到 static/img 目录下,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ tree static 
static
└── static
├── css
├── img
│ ├── nodejs_express_1.jpeg
│ ├── nodejs_express_2.jpeg
│ ├── nodejs_express_3.jpeg
│ ├── nodejs_express_4.jpeg
│ └── nodejs_express_5.jpeg
├── js
└── media

5 directories, 5 files

然后修改我们的 main.js 添加静态文件处理功能

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
var express = require('express');
var app = express();

app.use(express.static('static'));


// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("应用实例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js                                              
Node.js Express 应用范例,访问地址为 http://:::8080

在浏览器中访问 http://127.0.0.1:8080/static/img/nodejs_express_1.jpeg

Express 路由 GET 方法

现在我们使用 Express 开发一个表单,然后接收和处理表单传过来的数据

form_get.html

1
2
3
4
5
6
7
8
9
10
<html>
<body>
<form action="http://127.0.0.1:8080/get">
<p>姓: <input type="text" name="first_name">

名: <input type="text" name="last_name">
<input type="submit" value="提交">
</form>
</body>
</html>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
var express = require('express');
var app = express();

app.use(express.static('static'));


// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


app.get('/form_get.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.query.first_name,
"last_name":req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})



// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_get.html,我们可以向表单输入数据,然后提交

Express 路由 POST 方法

上面我们已经用 GET 方法提交了表单,现在我们在开发一个表单,使用 POST 方法来提交表单

我们需要使用 body-parser 插件来解析 POST 提交的表单

form_post.html

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<body>
<form action="http://127.0.0.1:8080/post" method="POST">
POST 方法提交表单

姓: <input type="text" name="first_name">

名: <input type="text" name="last_name">
<input type="submit" value="提交">
</form>
</body>
</html>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
var express = require('express');
var app = express();
var bodyParser = require('body-parser');


app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })



// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


app.get('/form_post.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.body.first_name,
"last_name":req.body.last_name
};
res.end(JSON.stringify(response));
})


app.get('/form_get.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.query.first_name,
"last_name":req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})



// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_post.html

我们可以向表单输入数据,然后提交

Express 上传文件范例

我们已经学过了如何用 POST 方法提交表单,现在我们学习如何用 POST 方法开发上传文件范例

上传文件的表单需要设置 form 的 enctype 属性为 “multipart/form-data”

Express 项目中需要设置

1
2
3
var multer  = require('multer');

app.use(multer({ dest: '/tmp/'}).array('image'));

form_upload.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
<head>
<title>文件上传表单</title>
</head>
<body>
<h3>文件上传:</h3>
选择一个文件上传:
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="image" size="50" />
<br />
<input type="submit" value="上传文件" />
</form>
</body>
</html>

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
var express = require('express');
var fs = require('fs');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');

app.use(multer({ dest: '/tmp/'}).array('image'));
app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })



// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


app.get('/form_upload.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_upload.html" );
})

app.post('/upload', function (req, res) {

console.log(req.files[0]); // 上传的文件信息

var des_file = __dirname + "/" + req.files[0].originalname;
fs.readFile( req.files[0].path, function (err, data) {
fs.writeFile(des_file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files[0].originalname
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
})


app.get('/form_post.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.body.first_name,
"last_name":req.body.last_name
};
res.end(JSON.stringify(response));
})


app.get('/form_get.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.query.first_name,
"last_name":req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})



// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/form_upload.html,我们可以选择图片,然后点击上传按钮

Express 的 response 对象的 res.cookie() 方法和 res.clearCookie 方法可以用来设置和清除 Cookie

当使用 cookie-parser 中间件时,还可以设置签名 Cookie 和 获取 Cookie 信息

下面我们就简单的演示下这些方法的使用

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
var express = require('express');
var fs = require('fs');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var cookieParser = require('cookie-parser')

app.use(cookieParser());
app.use(multer({ dest: '/tmp/'}).array('image'));
app.use(express.static('static'));

// 创建 application/x-www-form-urlencoded 编码解析
var urlencodedParser = bodyParser.urlencoded({ extended: false })



// 主页输出 "Hello World"
app.get('/', function (req, res) {
console.log("主页 GET 请求");
res.send('Hello GET');
})


app.get('/cookie/set',function(req,res){
res.cookie('sitename', 'Hello World', { maxAge: 900000, httpOnly: true })
res.write('<h1>设置 Cookie </h1>');
res.write('<p>设置了 Cookie: sitename="Hello World" </p>')
res.end('<p><a href="/cookie/get">获取 Cookie</a></p>');
});

app.get('/cookie/get',function(req,res){
res.write("<h1>获取 Cookie 信息 </h1>");
res.write("<p>本站的 Cookie 信息如下:" + JSON.stringify(req.cookies) + "</p>");
res.end();
});

app.get('/form_upload.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_upload.html" );
})

app.post('/upload', function (req, res) {

console.log(req.files[0]); // 上传的文件信息

var des_file = __dirname + "/" + req.files[0].originalname;
fs.readFile( req.files[0].path, function (err, data) {
fs.writeFile(des_file, data, function (err) {
if( err ){
console.log( err );
}else{
response = {
message:'File uploaded successfully',
filename:req.files[0].originalname
};
}
console.log( response );
res.end( JSON.stringify( response ) );
});
});
})


app.get('/form_post.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_post.html" );
})

app.post('/post', urlencodedParser, function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.body.first_name,
"last_name":req.body.last_name
};
res.end(JSON.stringify(response));
})


app.get('/form_get.html', function (req, res) {
res.sendFile( __dirname + "/" + "form_get.html" );
})

app.get('/get', function (req, res) {

// 输出 JSON 格式
var response = {
"first_name":req.query.first_name,
"last_name":req.query.last_name
};
console.log(response);
res.end(JSON.stringify(response));
})



// POST 请求
app.post('/', function (req, res) {
console.log("主页 POST 请求");
res.send('Hello POST');
})

// /user/del 页面响应
app.get('/user/dell', function (req, res) {
console.log("/del_user 响应 DELETE 请求");
res.send('删除页面');
})

// /user/list 页面 GET 请求
app.get('/user/list', function (req, res) {
console.log("/user/list GET 请求");
res.send('用户列表页面');
})

// 对页面 abcd, abxcd, ab123cd, 等响应 GET 请求
app.get('/ab*cd', function(req, res) {
console.log("/ab*cd GET 请求");
res.send('正则匹配');
})


var server = app.listen(8080, function () {

var host = server.address().address
var port = server.address().port

console.log("Node.js Express 应用范例,访问地址为 http://%s:%s", host, port)

})

运行以上 Node.js Express 范例,输出结果如下

1
2
$ node main.js                   
Node.js Express 应用范例,访问地址为 http://:::8080

浏览器访问 http://127.0.0.1:8080/cookie/get.html,我们可以选择图片,然后点击上传按钮