当前位置: 首页 > news >正文

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() 查询满足条件的记录的总条数

六、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)
})

相关文章:

  • 【工具】使用 sealos 部署 k8s 集群
  • LeetCode 每日一题 2022/9/19-2022/9/25
  • T1046判断一个数能否同时被3和5整除 (信息学一本通C++)
  • Canal + MySQL + Zookeeper + Kafka 数据实时同步
  • 我们如何一键将录音转换成文字?
  • 给计算机专业新生的一些学习建议
  • Java处理时间格式CST和GMT转换
  • VUE之组合式API
  • WebMagic
  • 梧桐树在售的金玉满堂增额终身寿险历久弥新,持续补充养老现金流
  • LDR6035 PD单USB-C口可充放电OTG协议芯片特点
  • php案例 解决cookie失效后使用session的问题
  • 远程访问服务器jupyter notebook
  • 便捷式物流成本核算教程
  • MAC实现Web UI自动化Safari
  • CAP 一致性协议及应用解析
  • chrome扩展demo1-小时钟
  • js写一个简单的选项卡
  • MYSQL 的 IF 函数
  • Odoo domain写法及运用
  • orm2 中文文档 3.1 模型属性
  • OSS Web直传 (文件图片)
  • Python学习之路13-记分
  • Redash本地开发环境搭建
  • select2 取值 遍历 设置默认值
  • Spark RDD学习: aggregate函数
  • vue.js框架原理浅析
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 理解在java “”i=i++;”所发生的事情
  • 前端存储 - localStorage
  • 通过几道题目学习二叉搜索树
  • 微信小程序填坑清单
  • 我的面试准备过程--容器(更新中)
  • 我建了一个叫Hello World的项目
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​Spring Boot 分片上传文件
  • #Spring-boot高级
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • #我与Java虚拟机的故事#连载16:打开Java世界大门的钥匙
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)计算机毕业设计SSM智能化管理的仓库管理
  • (利用IDEA+Maven)定制属于自己的jar包
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • ./configure,make,make install的作用(转)
  • .NET建议使用的大小写命名原则
  • .net与java建立WebService再互相调用
  • [20180129]bash显示path环境变量.txt
  • [3300万人的聊天室] 作为产品的上游公司该如何?
  • [ACTF2020 新生赛]Upload 1
  • [C#]C# OpenVINO部署yolov8图像分类模型
  • [C++]——带你学习类和对象