26_TokenMongodb
一、multipart
文件上传
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W4nga04f-1663946058082)(C:\Users\JReal\AppData\Roaming\Typora\typora-user-images\image-20220920113517076.png)]
server.js
// 1 导入express
const express = require('express');
const path = require('path')
const cors = require('cors');
const userRouter = require('./router/user')
// 2 创建express的实例
const app = express();
// 4 配置路由
// 使用bodyParser中间件
app.use(express.json()); // application/json
app.use(express.urlencoded()) // application/x-www-form-urlencoded
// 使用静态资源中间件
app.use(express.static(path.join(__dirname,'public')))
// 使用第三方cors中间件
// 需要下载,导入,使用
// 下载: npm i cors
app.use(cors())
// 使用路由中间件
app.use('/user',userRouter)
// 错误处理中间件放在最后
app.use((err,req,res,next)=>{
console.log(err);
// 只要有错误就给前端返回一个错误页面
res.sendFile(path.join(__dirname,'public','err.html'))
})
// 3 监听端口
app.listen(8080)
user.js
// 1 导入express
const express = require('express');
const multiparty = require('multiparty')
const fs = require('fs');
const path = require('path')
// 2 创建路由实例
const router = express.Router();
// 3 配置路由实例
// 登录接口
router.post('/login',(req,res)=>{
// 先获取请求主体里面的用户名(username)和密码(password)
console.log(req.body) ;// {username:xxx,password:yyy}
let {username,password} = req.body;
if(username&&password){
// 就去数据管理中心查询是否有这个用户,如果有就返回一个结果
res.json({code:1,msg:'登录成功',data:{username,banji:'sz2209'}})
}
})
// 文件上传接口
router.post('/upload',(req,res)=>{
// 要使用第三方中间件 multiparty 来处理multipart/form-data格式
// 要下载,导入,使用
// 每个请求都创建一个form实例
let form = new multiparty.Form();
// 调用form.parse来解析post请求主体
form.parse(req,(err,fields,files)=>{
// console.log('fields是表单数据里面的非文件内容')
// console.log(fields); // {user:['lucy'],pw:['11111']}
// console.log('files是表单数据里面的文件内容')
// console.log(files)
/*
{
filedata: [
{
fieldName: 'filedata',
originalFilename: 'package.json',
path: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\XPORThYu-hNPl_d6Qf_NrsJd.json',
headers: [Object],
size: 318
}
]
}
*/
try{
var file = files.filedata[0];
// 把文件从临时目录中读取出来,写到public文件夹的img文件夹中
var data = fs.readFileSync(file.path);
fs.writeFileSync(path.join(__dirname,'..','public/img',file.originalFilename),data);
}catch(err){
res.json({
code:0,
msg:'文件上传失败'
});
return;
}
res.json({
code:1,
msg:'文件上传成功',
url:'/img/'+file.originalFilename
})
})
})
// 4 导出
module.exports = router;
index.html
let xhr = new XMLHttpRequest();
xhr.open('post','http://localhost:8080/user/login')
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')
xhr.send('username=lucy&password=123456')
xhr.onload = function(){
console.log(xhr.responseText)
}
uploading.html
<!-- 表单天生自带提交动态 -->
<!--
表单提交的时候会跳页,跳转到action里的地址
前端的表单主体里面有文件
那么表单的格式就不是 application/x-www-form-urlenocded
表单格式就要改成 enctype="multipart/form-data"
-->
<form action="http://localhost:8080/user/upload" method="post" enctype="multipart/form-data">
<input type="file" name="filedata">
<input type="text" name="user">
<input type="text" name="pw">
<input type="submit">
</form>
<!-- 使用ajax提交文件 -->
<input type="file" name="filedata" id="ajax">
<button>点击使用ajax提交文件</button>
<img src="" alt="">
<script>
let fileInp = document.querySelector('#ajax')
// fileInp.onchange = function(){
// console.dir(fileInp.files)
// }
// 点击按钮button,通过ajax提交form-data格式的post请求
document.querySelector('button').onclick = function(){
let xhr = new XMLHttpRequest();
xhr.open('POST','http://localhost:8080/user/upload');
// 创建一个formData对象
let form = new FormData();
// 给form里面添加key/value
form.append('filedata',fileInp.files[0])
xhr.send(form)
xhr.onload = function(){
console.log(xhr.responseText)
let obj = JSON.parse(xhr.responseText)
document.querySelector('img').src = "http://localhost:8080"+ obj.url;
}
}
- 文件上传前端部分
enctype='multipart/form-data'
<input type="file" id="box">
box.onchange = function(){
let form = new FormData();
form.append('filedata',box.files[0])
let xhr = new XMLHttpRequest();
xhr.open('post','http://localhost:9090/upload')
xhr.send(form)
xhr.onload = function(){
console.log(xhr.responseText)
}
}
- 文件上传后端部分
const express = require('express');
const multiparty = require('multiparty')
const fs = require('fs')
const app = express()
// 文件上传接口
app.post('/upload', (req, res, next)=>{
// 每次访问该接口,都新建一个form对象来解析文件数据
var form = new multiparty.Form()
form.parse(req, (err, field, files) =>{
if (err) {
res.json({code:0,msg:'文件上传失败'})
} else {
var file = files.filedata[0]
// 读取文件
var data = fs.readFileSync(file.path)
// 写入文件
var filePath = './public/'+ file.originalFilename
fs.writeFileSync(filePath,data)
// 管道流,图片写入指定目录
res.json({success:1})
}
})
})
app.listen(9090)
二、token
2.1 Token的引入
- 客户端频繁向服务端请求数据
- 服务端要频繁去数据库查询用户名和密码并进行对比
- 判断用户是否有权限请求接口数据
- 没有有一种办法可以不用频繁进行数据库验证呢?
- Token便应运而生
- Token的目的
- 减轻服务器的压力
- 减少频繁的查询数据库
- Token从哪里来
- token在服务端生成
- 当用户登录时,或者调用指定接口时,会返回Token给客户端用户
- 客户端用户收到Token后
- 保存在前端(比如保存在localStorage中)
- 之后再请求其它有访问权限的后端接口时
- 需要把Token携带上传递给后端进行验证
- Token长什么样
- eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
- 如何把Token传递至后端呢
- 这根据后端的要求
- 通常会把Token放在 headers 中进行传递
2.2 后端生成和验证token
var express = require('express');
var app = express();
var cors = require('cors');
var path = require('path')
var jwt = require('jsonwebtoken');
app.use(cors())
app.get('*',function(req,res,next){
if(req.url!="/getToken"){
var token = req.headers.authorization;
jwt.verify(token, 'shhhhh', function(err,decoded){
if(decoded&&decoded.foo){
next()
}else{
res.send('请求不合法')
}
});
}else{
next()
}
})
app.get('/list',function(req,res){
res.send({success:'hello'})
})
app.get('/getToken',function(req,res){
var token = jwt.sign({foo:'bar'},'shhhhh');
res.send({
token
})
});
app.listen(8888)
2.3 前端发送携带token
<input type="button" id="btn" value="点击获取token">
<input type="button" id="list" value="点击请求list数据">
<script>
document.querySelector('#btn').onclick = function(){
let xhr = new XMLHttpRequest()
xhr.open('GET','/getToken')
xhr.send()
xhr.onload = function(){
window.localStorage.setItem('token',data.token)
}
}
document.querySelector('#list').onclick = function(){
let xhr = new XMLHttpRequest()
xhr.open('GET','/list')
xhr.setRequestHeader('authorization',window.localStorage.getItem('token'))
xhr.send()
xhr.onload = function(){
console.log(xhr.responseText)
}
}
</script>
三、MongoDB数据库
3.1 什么是MongoDB
- MongoDB是一个基于分布式文件存储的数据库
- 由C++编写
- 主要为WEB应用提供可扩展的高性能数据存储解决方案。
- 特点:高性能、易部署、易使用、存储数据非常方便。
3.3 安装MongoDB
- 双击mongodb-windows-x86_64-4.4.1-signed.msi安装包
- 安装过程中,取消勾选“MongoDB Compass”
- 它是MongoDB官方的图形化工具,无须安装
- 配置环境变量:
- 右键点击计算机
- 属性
- 高级系统设置
- 环境变量
- 用户变量
- 点击PATH
- 点击编辑按钮
- 在最后面加上 ;C:\Program Files\MongoDB\Server\4.2\bin;
- 注意:C:\Program Files\MongoDB\Server\4.2\bin根据你的具体安装路径决定
- 在D盘创建一个data文件夹,用于存放数据库的内容
- 在命令行输入:mongod --dbpath “D:\data”
- 就可以启动mongodb数据库服务了
3.2 几个术语
database
数据库
- 数据库 database,类似存储json文件的文件夹
collection
数据库集合
- 数据库表 colleciton,类似json文件
document
数据记录行
- 数据记录行 document,类似json里面的一个对象,键值对的形式
fields
数据字段
- 数据字段 field 类似json里面的一条记录的成员名
primary key
主键
- 数据字段的某一个如果条件的这个成员都是唯一的,这就是主键
- 默认以_id作为主键
四、Robo3T 数据库可视化工具
- 双击robo3t-1.4.1-windows-x86_64-122dbd9.exe
- 点击安装填写相关信息
- 启动 MongoDB服务
- 启动 Robo3T
- 在Robo3T中创建连接、完成
五、命令行操作mongodb
- 使用Robo3T
- 在命令行输入mongod启动mongodb数据库服务
- 双击启动Robo 3T软件
- 点击Create弹出窗口
- Type:不要修改
- Name:随意
- Address:localhost:27017 不要修改
- 点击save
- 点击connection连接成功
- 打开shell命令行
- 在你要操作的数据库上点击右键,弹出的快捷菜单点击:open shell
- 输入命令
- 点击运行按钮(绿色的三角形)或者按ctrl+enter即可执行
- 常用的shell命令
- 1、帮助命令
- help
- db.help()
- 2、数据库操作命令
- show dbs
- use dbname 切换数据库
- db / db.getName() 查看当前数据库名称
- db.stats() 显示当前DB的状态
- db.version() 查看当前DB的版本
- db.getMongo() 查看当前DB的连接的主机地址
- db.dropDatabase() 删除当前DB
- 3、创建数据库和集合
- use project 不存在就创建,存在就切换至
- db.createCollection(‘user’) // 创建user集合
- show dbs
- show collections / db.getCollectionNames()
- db.getCollection(‘music’) 获取指定集合
- db.printCollectionStats() 打印指定集合的状态
- 4、集合中的文档操作:
- db.user.insertOne({}) 向集合中插入文档
- db.user.insertMany([{},{}])
- db.user.save({})
- db.user.updateOne({“name”:“cyr”}, {$set:{“age”:100}})
- db.user.updateMany({},{$set:{}})
- db.user.deleteOne({“name”:“jiaming”})
- db.user.deleteMany({})
- db.user.remove({}) // 要指出删除的条件
- save和insert的区别:
- 新增的数据中存在主键,则再次插入相同的主键时insert() 会提示错误
- 而save() 则更改原来的内容为新内容
- 没有saveMany命令
- 5、聚集集合查询
- db.集合名.find({查询条件对象},{显示对象})
- db.user.find() 查询所有记录
- db.user.find({age:22}) 查询age=22的记录
- db.user.find({age:{$gt: 22}}) 查询age>22的记录
- db.user.find({age:{$lt: 22}}) 查询age<22的记录
- db.user.find({age:{$gte: 22}}) 查询age>=22的记录
- db.user.find({age:{$lte: 22}}) 查询age<=22的记录
- db.user.find({age:{$gte:20, $lte:30}}) 查询age>=20 && age<=30的记录
- db.user.find({name:/cyr/}) 查询name中包含’cyr’的记录
- db.user.find({name:/^cyr/}) 查询name以’cyr’开头的记录
- db.user.find({},{name:1,age:1}) 查询所有记录,只返回name和age字段(1-显示 0-不显示)
- db.user.find({age:{$gt:20}},{name:1,age:1}) 查询age>20的记录,只返回name和age字段
- db.user.find().sort({age:1}) 按age进行升序排列
- db.user.find().sort({age:-1}) 按age进行降序排列
- db.user.find({},{name:1,age:1,_id:0}).sort({age:1})
- db.user.find({name:‘cyr’,age:22}) 查询name=‘cyr’ && age=22的记录
- db.user.find().limit(5) 只查询前5条记录
- db.user.find().skip(10) 查询10条以后的所有数据
- db.user.find().skip(5).limit(5) 查询第6~10条记录
- db.user.find({$or:[{age:20},{age:25}]}) 查询age=20或者age=25的记录
- db.user.findOne() 查询满足条件的第一条记录
- db.user.find({age:{$gte:25}}).count() 查询满足条件的记录的总条数
- 1、帮助命令
六、express
操作数据库
- 操作mongodb数据库
- 使用第三方模块:mongoose
- 初始化package.json:npm init
- mongoose的安装:npm install mongoose -S
- mongoose使用步骤:
- 1 导入mongoose模块
- 2 连接数据库
- 3 创建数据集合
- 4 执行增删改查语句
1.建立链接
// 导入mongoose模块
const mongoose = require('mongoose');
// 连接数据库,hello是要操作的数据库名称
mongoose.connect('mongodb://localhost:27017/hello',{ useNewUrlParser: true ,useUnifiedTopology: true });
// 获取数据库连接
const db = mongoose.connection;
// 监听数据连接错误和第一次打开事件
db.on('error',function(){
console.log('数据库连接错误')
})
db.once('open',function(){
console.log('数据库连接成功')
})
2.Schema
创建集合
var db = require('./05node-mongodb-connect');
// 导入mongoose模块
var mongoose = require('mongoose');
// 创建集合的字段名和值的数据类型
var articleSchema = mongoose.Schema({
title: String,
content: String,
createTime: Number,
username: String
});
// 创建集合articles
var articleModel = mongoose.model('article', articleSchema);
module.exports = {
articleModel
}
3.insetMany()
插入数据行
const { articleModel } = require('./node-mongodb-collection');
//插入一条数据
articleModel.insertMany({
title:"hello zhaoliu",
content:"我是文章3",
createTime:234234324,
username:"zhaoliuxxxx"
}).then((data)=>{
//data就是插入的那个数据
console.log(data);
})
//插入多条数据
articleModel.insertMany([{
title:"hello zhangsan",
content:"我是文章1",
createTime:2312321434,
username:"zhangsan"
},{
title:"hello lisi",
content:"我是文章2",
createTime:3432445435,
username:"lisi"
}]).then((data)=>{
//data就是插入的那些数据
console.log(data);
})
4.find()
查询数据
const {articleModel} = require('./06node-mongodb-collection');
//根据条件查找
articleModel.find({createTime:{$gt:234234324}}).then(data=>{
//data就是查询到的数据
console.log(data);
})
//根据主键_id查找
articleModel.findById('5f968f5231cbb518b0cda099').then(data=>{
//data就是查询到的数据
console.log(data);
})
5.updateOne()
修改数据、更新数据
const {articleModel} = require('./06node-mongodb-collection');
//更新一条数据
articleModel.updateOne({username:'zhangsan'},{$set:{username:'zhangsan111'}})
.then((data)=>{
//data表示更新是否成功的信息
console.log(data)
})
//更新多条数据
articleModel.updateMany({username:'zhaoliuxxxx'},{$set:{username:'赵六1111'}})
.then(function(data){
//data表示更新是否成功的信息
console.log(data)
})
6.deleteOne()
删除数据
const {articleModel} = require('./06node-mongodb-collection');
//删除一条数据
articleModel.deleteOne({username:'赵六1111'})
.then(function(data){
//data表示删除是否成功的信息
console.log(data)
})
//删除多条数据
articleModel.deleteMany({username:'赵六1111'})
.then(function(data){
//data表示删除是否成功的信息
console.log(data)
})