express搭建web服务器、路由、get、post请求、multer上传文件、EJS模板引擎的使用
express模板引擎怎么使用 地址:http://www.expressjs.com.cn/guide/using-template-engines.html
首先建立一个server.js
之后npm init初始化一下
安装express
npm install express --save
在server.js中写入
在运行之前安装一个nodemon插件(全局安装),它可以在服务器代码发生改变时自动启动(方便开发)
npm install -g nodemon
运行
nodemon
nodemon会自动去找server.js文件并且运行,实际上就是执行node server.js
如果服务器入口文件叫app.js,那么可以执行nodemon app启动
之后访问localhost:3000或者http://127.0.0.1:3000就会会看到出现服务器返回的内容:服务器响应!!!好简单的express服务器已经完成了,这比http服务器写路由要简单的多
上诉的服务器res.send(),返回了个字符串,当然也可以返回json,而且返回json时,不用专门用JSON.stringify()来转换,express框架已经可以自动转换了
var express = require("express");//引入express var app = express();//创建express实例 app.get("/",function(req,res){//定义路由 还有post delete方法 是express定义的 var responseObject = {//也可以是数组 数组也会转化为json name:"大伟" } res.send(responseObject) }); app.listen(3000); console.log("listening to port 3000")
也可以把res.send()换成res.json(),前者既可以返回纯文本也可以返回json后者只能返回json
-----------------------------------------------------------------------------------------------------
express路由
var express = require("express");//引入express var cors = require('cors'); var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 app.get("/profile/:id/:name",function(req,res){//:后面的id和:name,代表是可变的 console.log(req.method);//req.method可以拿到前端请求用的是什么方法 console.dir(req.params);//req.params可以拿到路由上定义的参数值 console.dir是在终端打印出对象的内容 var responseObject =req.method; res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.listen(3000); console.log("listening to port 3000")
上面定义了/profile/:id/:name这样的路由 那么我们在浏览器访问:localhost:3000/profile/xxx/xxx都可以访问到这个页面 而且在服务端还可以拿到客户端输入的这些值
另外,express的路由 也可以用正则表达式去定义
var express = require("express");//引入express var cors = require('cors'); var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 app.get("/profile/:id/:name",function(req,res){//:后面的id和:name,代表是可变的 console.log(req.method);//req.method可以拿到前端请求用的是什么方法 console.dir(req.params);//req.params可以拿到路由上定义的参数值 console.dir是在终端打印出对象的内容 var responseObject =req.method; res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
上面用正则定义的路由 可以匹配abcd 或 acd 但是a22cd就匹配不了,这需要对正则有一定了解
-------------------------------------------------------------------------------------------------------------------------
express服务器端如何取到 查询字符串(也就是url ?后面的内容)
下面来新定义一个接口
var express = require("express");//引入express var cors = require('cors'); var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
很简单 req.query里面就是查询字符串
---------------------------------------------------------------------------------------------------------------------------------
下面我们说一下express中的post请求
在node基础中,我们用了querystring来处理post请求传来的值,在express中我们用body-parser这个插件来处理post传来的值
首先安装这个插件:
npm install body-parser --save
之后在server.js中写一个post请求
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 app.post("/",function(req,res){ console.dir(req.body);//取到post请求传来的数据 res.send("success"); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
我们之前都是用表单来发出post请求的,这次我们用postman来模拟post请求
我们进入postman后在地址栏中输入http://localhost:3000 之后请求方法改成POST,之后选择x-www-form-urlencoded(它与form-data的区别是 form-data可以传输文件)
之后填入key以及value,然后点击send,就可以看到请求的响应了(在body中看)
除了以上方法外,也可以在一个html页面中,用jquery的ajax方法发送post请求:
function aa(){ $.post( 'http://127.0.0.1:3000/', { name: 'admin', password: '123' }, function(result) { console.log(result) $("#inp").val(result) } ); }
上诉服务器用bodyparser.urlencoded({extended:false})中间件,来处理post请求发送的form表单数据的,如果我们发送的是json数据该怎么处理呢?:
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser 中间件 var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 // app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 urlencoded是处理form表单格式的数据的 app.use(bodyParser.json());//json是处理 json数据的 app.post("/",function(req,res){ console.dir(req.body); res.send(req.body.name); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
将urlencoded换成json就可以处理post传来的json格式的数据了!!!
那么怎么让不同接口用不同的中间件处理不同的数据呢?
可以像下面这样:
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser 中间件 var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 // app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 urlencoded是处理form表单格式的数据的 // app.use(bodyParser.json());//json是处理 json数据的 var jsonParser = bodyParser.json();//处理json数据 var urlencodedParser = bodyParser.urlencoded({extended:false});//处理form表单格式数据 app.post("/",urlencodedParser,function(req,res){//这个接口处理form表单数据 console.dir(req.body); res.send(req.body.name); }) app.post("/upload",jsonParser,function(req,res){//这个接口处理json数据 console.dir(req.body); res.send(req.body.name); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
-----------------------------------------------------------------------------------------------------------------------------
如何把文件上传到服务器中呢?
这需要一个库multer
Multer 是一个 node.js 中间件,用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。它是写在 busboy之上非常高效。
注意: Multer 不会处理任何非 multipart/form-data
类型的表单数据。
先安装这个库
npm install --save multer
先在服务器同目录下写一个form.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> </head> <body> <form action="/upload" method="POST" enctype="multipart/form-data"> <h2>图片上传</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form> </body> </html>
在server.js添加:
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser 中间件 var fs = require('fs');//引入文件模块 var multer = require('multer');//文件上传需要用到 var upload = multer({dest:'uploads/'});//指定上传的目录 这里指向当前目录下的uploads目录 var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 // app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 urlencoded是处理form表单格式的数据的 // app.use(bodyParser.json());//json是处理 json数据的 var jsonParser = bodyParser.json();//处理json数据 var urlencodedParser = bodyParser.urlencoded({extended:false});//处理form表单格式数据 app.get("/form",function(req,res){//文件上传页面 var form = fs.readFileSync("./form.html",{encoding:'utf8'}); res.send(form); }) app.post("/upload",upload.single('logo'),function(req,res){//上传文件的接口 res.send({'ret_code':0}) }) app.post("/",urlencodedParser,function(req,res){//这个接口处理form表单数据 console.dir(req.body); res.send(req.body.name); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
以上代码 访问form路由,会呈现出表单页面
当选择过文件点击提交后会 请求upload接口,此接口会将客户端传过来的文件转换成二进制文件,放在当前目录的uploads文件下;
以上已经基本完成了文件上传到服务器的功能,但是上传到服务器的文件名称是一大串hash值,分不清楚到底是哪个文件(7e059868d06f6a6d0fafb716c1c4c5cc)
下面我们需要对文件名称和路径进行进一步设置:
server.js
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser 中间件 var fs = require('fs');//引入文件模块 var multer = require('multer');//文件上传需要用到 var createFolder = function(folder){ try{ fs.accessSync(folder);//文件可访问性检查 如果这个文件可访问就没事 }catch(e){ fs.mkdirSync(folder);//如果访问不到 就创建个这样的文件 } } var uploadFolder = './upload/'; createFolder(uploadFolder); var storage = multer.diskStorage({//磁盘存储引擎 destination: function (req, file, cb) {//设置存放文件的路径 cb(null, uploadFolder) }, filename: function (req, file, cb) {//设置文件的名称 cb(null, file.originalname + '-' + Date.now()) } }) var upload = multer({ storage: storage }); var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 // app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 urlencoded是处理form表单格式的数据的 // app.use(bodyParser.json());//json是处理 json数据的 var jsonParser = bodyParser.json();//处理json数据 var urlencodedParser = bodyParser.urlencoded({extended:false});//处理form表单格式数据 app.get("/form",function(req,res){//文件上传页面 var form = fs.readFileSync("./form.html",{encoding:'utf8'}); res.send(form); }) app.post("/upload",upload.single('logo'),function(req,res){//上传文件的接口 console.dir(req.file);//返回上传过来的文件信息 res.send({'ret_code':0}) }) app.post("/",urlencodedParser,function(req,res){//这个接口处理form表单数据 console.dir(req.body); res.send(req.body.name); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
以上就是上传文件功能
这里做一个补充,当我们想把一个html页面返回给前台时,不用必须用fs去读取之后再响应到页面,可以直接用express提供的res.sendFile(__dirname+'/form.html');
app.get("/form",function(req,res){//文件上传页面 res.sendFile(__dirname+'/form.html') })
------------------------------------------------------------------------------------------------------------------------------
下面说一下模板引擎,那么模板引擎的使用场景是什么呢?
就比如上面的form路由会返回一个html页面到前台,但是我们想把res.params.name这个变量传递给html,将这个变量当做html页面的一部分,这该怎么做呢?下面就用到了模板引擎;
下面来介绍express中的一种模板引擎EJS
先安装一下:
npm install ejs --save
可以在百度搜一下 express template 看看express模板引擎怎么使用 地址:http://www.expressjs.com.cn/guide/using-template-engines.html
下面来使用一下,
首先更改一下server.js文件中内容
var express = require("express");//引入express var cors = require('cors'); var bodyParser = require('body-parser');//引入body-parser 中间件 var fs = require('fs');//引入文件模块 var multer = require('multer');//文件上传需要用到 var createFolder = function(folder){ try{ fs.accessSync(folder);//文件可访问性检查 如果这个文件可访问就没事 }catch(e){ fs.mkdirSync(folder);//如果访问不到 就创建个这样的文件 } } var uploadFolder = './upload/'; createFolder(uploadFolder); var storage = multer.diskStorage({//磁盘存储引擎 destination: function (req, file, cb) {//设置存放文件的路径 cb(null, uploadFolder) }, filename: function (req, file, cb) {//设置文件的名称 cb(null, file.originalname + '-' + Date.now()) } }) var upload = multer({ storage: storage }); var app = express();//创建express实例 app.use(cors());//为了解决跨域问题 app.set('view engine', 'ejs');//使用模板引擎 我们这里使用ejs模板引擎 // app.use(bodyParser.urlencoded({extended:false}));//使用body-parser插件 urlencoded是处理form表单格式的数据的 // app.use(bodyParser.json());//json是处理 json数据的 var jsonParser = bodyParser.json();//处理json数据 var urlencodedParser = bodyParser.urlencoded({extended:false});//处理form表单格式数据 app.get("/form/:name",function(req,res){//文件上传页面 var person = req.params.name; res.render('form',{person:person}) }) app.post("/upload",upload.single('logo'),function(req,res){//上传文件的接口 console.dir(req.file);//返回上传过来的文件信息 res.send({'ret_code':0}) }) app.post("/",urlencodedParser,function(req,res){//这个接口处理form表单数据 console.dir(req.body); res.send(req.body.name); }) app.get("/",function(req,res){ console.dir(req.query); res.send(req.query);//拿到查询字符串 }); app.get("/profile/:id/:name",function(req,res){//定义路由 res.send("you requested to see a profile page"+req.params.id+req.params.name) }); app.get("/ab?cd",function(req,res){//?代表前面的b可以出现0次或一次 res.send("请求成功") }) app.listen(3000); console.log("listening to port 3000")
另外,需要在根目录建一个views文件夹,里面建一个form.ejs文件(其实就是html页面,只不过我们可以在里面用ejs的语法)
根据form/:name接口,我们是把一个person变量传给了模板,那么在form.ejs中怎么取到这个person变量呢?:
form.ejs:
<!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> </head> <body> <h1><%= person %></h1> <form action="/upload" method="POST" enctype="multipart/form-data"> <h2>图片上传</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form> </body> </html>
上面用<%= %>将person包裹住,就可以取到了
然后运行后,在地址栏输入localhost:3000/form/xxxx
这个xxxx就是person的值,在页面上就可以看到这个值了
-----------------------------------------------------------------------------------------------------------------------
上面简单使用了一下ejs模板引擎,下面我们更深入的去使用一下
我们传递给模板一个对象,里面宝行普通变量,也包含数组,来看看怎么将这些展示出来
先看路由里面怎样定义
app.get("/form/:name",function(req,res){//文件上传页面 var data = {name:"大伟",age:18,arr:["tom","july","bob"]}; res.render('form',{data:data}) })
form.ejs中
<!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>
</head>
<body>
<h1><%= data.name %></h1>
<h2><%= data.age %></h2>
<h3><%= data.arr %></h3>
<ul>
<% data.arr.forEach(function(item){ %>
<li><%= item %></li>
<% }) %>
</ul>
<form action="/upload" method="POST" enctype="multipart/form-data">
<h2>图片上传</h2>
<input type="file" name="logo">
<input type="submit" value="提交">
</form>
</body>
</html>
以上可以通过forEach把数组循环遍历出来
-----------------------------------------------------------------------------------------------------------------------------------------------
下面说一下模板共用问题,为什么要模板共用啊,比如说我们有一个网站,上面有一个导航条,每点击一下导航条会切换一个页面,如果每一个导航条在每个页面都写以一遍会比较繁琐,维护起来也比较麻烦。所以下面就说一下ejs的模板共用
首先我们在views中建立一个文件夹partials,这里面放着一些共用模板,我们在partials文件夹中建立一个header.ejs文件,加入这是一个导航条模板,它会被引入到其它模板中去,
views/partials/header.ejs:
<nav> <ul> <li><a href="javascript:">home</a></li> <li><a href="javascript:">about</a></li> </ul> </nav>
现在views中已经有一个form.ejs页面了,现在我们再建立一个about.ejs页面,我们要让form.ejs和about.ejs共用header.ejs模板;
在server.js中 建立对应about页面的路由
app.get("/about",function(req,res){//文件上传页面 res.render('about'); })
views/about.ejs:
<!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> </head> <body> <%- include('partials/header.ejs') -%> </body> </html>
同样在form.ejs中也这样引入即可
<!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> </head> <body> <%- include('partials/header.ejs') -%> <h1><%= data.name %></h1> <h2><%= data.age %></h2> <h3><%= data.arr %></h3> <ul> <% data.arr.forEach(function(item){ %> <li><%= item %></li> <% }) %> </ul> <form action="/upload" method="POST" enctype="multipart/form-data"> <h2>图片上传</h2> <input type="file" name="logo"> <input type="submit" value="提交"> </form> </body> </html>
这样,form.ejs和about.ejs就共用header.ejs模板了!!!
---------------------------------------------------------------------------------------------------------------------------------