后端。
把前端给的文件一一归类。
1、html页面放在views文件夹,并且要为每一个html页面设计一个路由
2、静态资源放在static或public
3、配置一些post中间件(因为要接收post传递过来的参数)
4、配置开放静态资源的中间件.
把用户本地的文件上传到服务器上。
必须是post,不写enctype 属性会默认enctype=application/x-www-form-urlencoded 在发送时编码所有字符。而设置enctype=“multipart/form-data” 不对字符编码。因此req.body不能用。
<form action="/注册地址" enctype="multipart/form-data" method="post">
<input name="username" placeholder="用户名"><hr>
<input type="file" name="f"><hr>
<button>注册button>
form>
npm install formidable
const formidable = require('formidable');
app.post('/upload',(req,res)=>{
//实例化接收文件数据的表单实例
const form = formidable({
uploadDir:'uploads',//上传的临时路径
})
//form.parse才是接收数据的方法,它是回调函数风格.
form.parse( req,(err,fields,files)=>{
//fields: 普通的表单数据 即除type="file"以外的数据 比如用户名、密码、性别...
//files: 文件数据 对象 { f: {size: 37186, path: '',name: 'erha1.jpg',type: 'image/jpeg' }}
});
});
应用:
//引入模块
const formidable = require('formidable');
app.post('/upload',(req,res)=>{
//实例化接收文件数据的表单实例
const form = formidable({
uploadDir:'uploads',//接收上传文件的路径,相对于当前cmd打开的路径。
//uploadDir:'/uploads',//要么不写路径,要么写绝对路径。如这里写路径则从c盘找。
})
//form.parse才是接收数据的方法,它是回调函数风格.
form.parse( req,(err,fields,files)=>{
//fields : 普通的表单数据 比如用户名、密码、性别... 除type="file"以外的数据
//files: 文件数据 对象 { f1: {size: 37186, path: '',name: 'erha1.jpg',type: 'image/jpeg' }}
let timeStamp = require('time-stamp')
let name = files.f1.name
let suffixName = path.extname( name ) //得到了后缀名.
let t = timeStamp('YYYYMMDDHHmmss')
let random = (Math.random() + '').substring(2,8)
//原路径
let oldpath = files.f1.path
//let newpath = 'uploads/' + files.f1.name //保留原文件名的文件上传
//新文件名
let newpath = 'uploads/' + t + ran + suffixName
//将文件传到upload路径
fs.renameSync( oldpath,newpath )
res.send('文件上传')
} )
})
保留原文件名
生成及其他文件名
1)年月日时分秒 + 8位随机数
2)使用第三方模块uuid,使用方法:https://www.npmjs.com/package/uuid。
Cookie的产生也是HTTP的特点所决定的。HTTP协议有一个非常重要的特点是无状态的,也就是说当客户端请求服务器,每一个请求和响应结束以后,这次的连接是马上断开的(也是为了释放资源)。同时服务器是不保留连接者相关的信息。这就说明了,Cookie要解决HTTP无状态的问题。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AZR8pAxa-1635505515691)(img\3-7cookie的现实场景.jpg)]
最最常见的就是,表单传递了用户名和密码参数,服务器要在对应的/login路由中判断用户名和密码是否验证成功,成功以后才能告诉浏览器(要保存一个用户状态):后端决定是否存储这个状态。
其实咱们第2阶段学的localStorage 和cookie是很像的。比如:在同一个项目中本地存储共享的。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s3ctrkr9-1635505515693)(img\3-8Cookie实现流程.jpg)]
npm install cookie-parser
const cookieParser = require("cookie-parser"); // 引入cookieparser中间件
app.use(cookieParser()); // 使用cookie-parser中间件 全局开启cookie功用
res.cookie(key,value[,option])
参数说明:
option:可选参数,{ maxAge : ms} 过期时间,表示多长时间后过期。以毫秒为单位
req.cookies
const cookieParser = require('cookie-parser')
//3. 使用cookie中间件
app.use( cookieParser() )
// 给定一个setcookie路由,它保存一个cookie( username:'zs' )
app.get('/setcookie',(req,res)=>{
//res.cookie( key,value )
res.cookie('username','aa')
res.cookie('username','bb') //之前有username则覆盖
res.cookie('age',20) //虽然是20,但也是存储为字符串类型
res.send('设置了cookie')
})
app.get('/setcookie2',(req,res)=>{
//演示过期时间
//含有过期时间(默认关闭浏览器,Cookie销毁)
//res.cookie( key,value[,options] ) //options{ maxAge:过期时间的 } 以毫秒为单位
res.cookie( 'a',1 )
res.cookie( 'b',2,{ maxAge:10*1000 } ) //10秒钟过期
res.send('设置cookie')
})
//给定一个getcookie路由,返回zs
app.get('/getcookie',(req,res)=>{
//req.cookies 获取所有的cookie
// res.send('返回cookie:xxx')
console.log( req.cookies )
res.send(req.cookies) //它是个对象
})
1)/login路由中通过req.cookie方法设置cookie
2)/welcome路由中设置欢迎界面
3)设计“/user/edit”路由,如果登录了可以正常访问,如果未登录则不让访问(权限管理雏形)
const cookieParser = require('cookie-parser')
app.use( cookieParser() )
// /login : 实现登录(保存cookie)
app.get('/login',(req,res)=>{
res.cookie( 'username','zs' )
res.send('登录成功')
})
// /welcome : 欢迎您:xxx, 未登录显示:游客
app.get('/welcome',(req,res)=>{
if( !req.cookies.username ){//取反为真代表未登录,代表username没有存储值
res.send('欢迎您:游客')
}else{
res.send('欢迎您 VIP:' +req.cookies.username )
}
})
// /user/edit: 用户编辑 ,如果未登录显示请登录
app.get('/user/edit',(req,res)=>{
if( !req.cookies.username ){
res.send('请登录跳转到某个页面')
}else{
res.send('可以看到用户编辑的表单页面' )
}
})
Session是另一种记录用户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。当服务端使用Session后,那么服务器会把Session信息存储在服务器上,同时Session标识也会记录在对应客户端上。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-td7GHYEL-1635505515696)(img\3-12session的现实场景.jpg)]
而储物柜给你条形码就可以理解为是 sessionid标识(理解为一把钥匙)。
session比cookie相对更安全。
Session存储在服务器
依赖cookie
可以存储任意类型
通过客户端的sessionid标识符区分Session
Session没有大小限制
不能设置过期时间(关闭浏览器销毁)
不同的浏览器之间不共享Session
存储session后在整个项目中有效(页面之间共享)
用cookie实现的那么session也都能实现 。而后端经常会使用session。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yw8q8cmL-1635505515697)(img/session.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zcT99hxV-1635505515698)(img\3-14Session实现流程.jpg)]
npm i cookie-session
const cookieSession = require("cookie-session"); // 引入cookieSession中间件
// 使用cookieSession 中间件
app.use(cookieSession({
//而且对象中必须要有keys属性,keys属性是个数组,数组中可以有任意个字符串值,用来加密session。
name: 'sessionids',//sessionid的名称,默认可以省略
keys: ['secret1','secret2','secret3'], //密钥锁
}))
req.session[key] = value
req.session
//1. 下载cookie-session中间件
//2. 引入
const cookieSession = require('cookie-session')
//3. 使用中间件 cookieSession在调用的时候必须传递一个对象
app.use( cookieSession({
keys:['adfsdf','adfsafd','asdfsa'],//给session钥匙进行加密
name:'aabbccddadf' ,//可传可不传,可以设置这把钥匙的名称 express:sess.sig/express:sess
}) )
app.get('/setsession',(req,res)=>{
//设置一个session
req.session.a=123
req.session.b='5555' //虽然可以存储任意类型,但很少存储函数的。
res.send('把数据存储到session中')
})
app.get('/getsession',(req,res)=>{
// res.send('得到session数据')
res.send( req.session )
})
渲染页面数据
1.下载ejs
npm i ejs
app.set('view engine', 'ejs')
3.在项目根目录下创建views文件夹
4.在views文件夹下创建模板文件
必须以 .ejs为后缀名
res.render('模板名称' [, data ])
参数说明:
参数1为模板名称,不需要添加后缀,会自动寻找对应后缀为.ejs文件
参数2为对象,向模板中传递的数据。
//之前我们的html中只是涉及到login.html和register.html
//而且拼接字符串也比较麻烦 。
app.set('view engine','ejs')
//为每一个页面设置路由 login
app.get('/login',(req,res)=>{
//页面必须在views中。
res.render('login') //我们可以使用render方法 进行渲染对应的ejs页面 文件必须以ejs后缀
//res.render( 无需加后缀 )
})
<%=变量名 %> //不限形式,在字符串里写也可以写变量
<% if( 条件 ){%>
<% }else{ %>
<% } %>
<% for(let i=0;i<数组.length;i++){ %>
循环项
<% }%>
说明:包含文件也是.ejs文件,无需携带后缀名
<%- include('公共文件路径') %>
<body>
<%- include('header') %>
<%- include('footer') %>
用户名: <%= username %>
<h2> 年龄: <%= age %>h2>
<img width="100" height="100" src="/uploads/<%= persons[i].avatar %>" alt="">
<% if( isPerson ){ %>
<h2>是个人h2>
<% }else{ %>
<h3>是个猴h3>
<% } %>
<% for( let i=0;i<persons.length;i++ ){ %>
<h4>姓名:<%= persons[i].username %>, 年龄:<%= persons[i].age %>h4>
<% } %>
<div>姓名:<%= person.username %>, 年龄:<%= person['age'] %>, 性别:<%= person.sex %>div>
body>
普通创建:下载express( 引入express、实例app、开启端口 )、模块化路由、定义post中间、设置cookie、设置ejs、大管家(package.json)
生成器工具express-generator(又称为脚手架工具) 可以快速创建一个应用的骨架,增加开发效率。
1.1 全局安装express-generator
npm i express-generator -g
1.2 使用脚手架初始化项目
express --view=ejs 项目包名
1.3 进入目录, 安装所有需要的模块
cd 项目包名
npm install
1.4 启动项目
npm run start
1.5 浏览器访问,默认3000端口
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fsbhJcRn-1635505515700)(C:/Users/Administrator/Desktop/%E8%AF%BE%E5%A0%82%E7%AC%94%E8%AE%B0/%E7%AC%AC%E4%B8%89%E9%98%B6%E6%AE%B5/show/this-is-the-803-web-notes/day09/%E7%AC%94%E8%AE%B0/assets/1634694442309.png)]
bin/www :启动文件
app.js:项目入口文件,初始化|全局的工作在app.js中进行定义
Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。
请求方法 | 编码格式 | 前端要传输的数据格式 | 后端如何获取 | 应用场景 |
---|---|---|---|---|
GET | url地址后面(querystring) | url?key1=value1&key2=value2 | 不需要中间件 :req.query | 获取数据 |
POST | applicaion/x-www-form-urlencoded | form-data: key1=value1&key2=value2 | express.urlencoded( { extend:true } ) :res.body | 提交数据 |
POST | applicaion/json(只能通过ajax) | request-payload: ‘{ “key1”:“value1”,“key2”:“value2” }’ | express.json() :res.body | |
POST | mutilpart/form-data(可以使用表单) | 文件流 | formidable : 实例对象.prase里的第二个参数 | 文件上传 |
DELETE | 同post | 删除数据 | ||
PUT | 同post | 更新数据 |
.body | |
| POST | mutilpart/form-data(可以使用表单) | 文件流 | formidable : 实例对象.prase里的第二个参数 | 文件上传 |
| DELETE | 同post | | | 删除数据 |
| PUT | 同post | | | 更新数据 |