一个简单的express框架和mongodb的联合使用的聊天小程序


事先声明: 这是本人根据express框架的学习,以及mongodb的使用做出来的一个十分简易的聊天小程序。
*实现功能:用户注册、登录、多个窗口用户实时聊天、可以发送图片进入聊天界面
缺点:本软件只是本人针对所学来进行功能实现,因此页面十分简洁,除了部分页面以外,没有使用css进行样式控制,mongodb服务只能在本机上使用,同局域网的其他用户无法访问到mongodb数据库,因此在其他的同局域网的电脑不能进行注册和登录功能

项目的目录结构

在这里插入图片描述

创建express 项目

express --view=ejs weChat // 创建一个项目名为WeChat的项目

cnpm i // 根据package.json的依赖内容,安装环境依赖

cd weChat // 进入WeChat目录

npm start  // 打开服务 打开浏览器访问localhost:3000 没有报错代表框架搭建成功

mongodb 服务器和客户端

mongod --dbpath d:\db // 打开mongodb服务 出现端口号为27017 代表服务开启成功

mongo  // 打开mongodb客户端,连接到mongodb服务,进行数据库操作

连接mongodb服务器

首先我们需要在WeChat项目下安装mongoose环境依赖

cnpm i mongoose --save 

在wechat目录下建立一个新的文件夹 db 在db下新建一个js文件 connect.js,具体代码如下

const mongoose = require("mongoose")  // 引入mongoose模块
// 连接到本地mongo数据库 端口号为27017 数据库为testDb 然后对connect函数的返回值进行错误处理,如果没有出错就打印连接成功,如果出错就打印连接失败
mongoose.connect('mongodb://localhost:27017/testDb', {useNewUrlParser: true},(err) => {
    if(!err){
        console.log("数据库连接成功")
    }else{
        console.log("数据库连接失败")
    }
});

connect.js 内容完成后 需要在routers下的index.js下面引用connect.js

var conn = require("../db/connect")

页面搭建

我只搭建了三个页面,登录,注册和聊天页面 (login.html,register.html,client.html)
记得都要引入jQuery js文件,js文件可以自己下载或者直接在www.npmJS.com官网上搜索,直接引入

<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<--登录-->
	<input type="text" id="username">
    <input type="password" name="password" id="password">
    <input type="button" value="提交" id="submit">
<--注册-->
	<input type="text" id="username">
    <input type="password" name="password" id="password">
    <input type="button" value="提交" id="submit">
<--客户端-->
	<div id="box"></div>
    <input type="text" id="text">
    <input type="button" value="发送" id="submit"><br />
    <input type="file" name="file" id="myFile">
    <input type="button" value="上传" id="upload">

配置登录注册路由

本部分属于users.js里面的接口,因此访问时需要使用/users/+接口,因此以下代码都是写在routes目录下的users.js中
在进行登录注册的时候我们需要使用以下几种模块
mongoose 模块 主要用于与mongo数据库进行链接
crypto 模块 主要作用是对密码进行加密

var login = require("mongoose")
var crypto = require("crypto")

引入模块完成后,我们对于mongoose模块需要定义一个模型

// 定义一个mongoose模型 集合的名字是 log 集合的数据格式是{username:String,password:String}
const Info = login.model("log",{username:String,password:String},"log")
注册接口
  • 定义访问接口为 /register 前段进行访问的接口为 /users/register
  • 获取前端传过来的注册信息(用户名和密码)get的接收方式为req.query,post的接收方式为req.body
  • 对获取到的密码进行加密,加密需要使用crypto模块
  • 对获取到的用户名与mongo数据库中log集合中的信息进行对比,是否有相同的用户名
  • 如果有相同的用户名,返回失败信息,如果成功,返回成功信息
router.post("/register", function (req, res, next) {
  // let file = path.resolve(__dirname,"../public/json/loginData.json")
  // console.log(file)
  let name = req.body.username
  let pwd = req.body.password
  // 对密码进行加密,加密的方法为sha256,update里面的信息可以随便填,输出的信息为hex格式(即十六进制)
  const hash = crypto.createHmac('sha256', pwd)
                   .update('hash')
                   .digest('hex');
  // 寻找是否具有相同的用户名
  Info.find({username:name}).then(response => {
    if(response.length > 0){
      res.json({
        status : 0,
        message:"用户名已被占用"
      })
    }else{
      Info({username:name,password:hash}).save().then(() => {
        res.json({
          status : 0,
          message:"用户注册成功,点击确定跳转登录界面"
        })
      })
    }
  })
})
注册界面js代码

给提交按钮绑定点击事件,获取用户名和密码,然后传递给后台,根据后台返回的数据判断用户是否注册成功

$("#submit").on("click",function() {
            var username = $("#username").val()
            var password = $("#password").val()
            $.post("/users/register",{username,password}).then(res => {
                if(res.status === 0){
                    alert(res.message)
                    location.href='./login.html'
                }else{
                    alert(res.message)
                }
            })
        })
登录接口
  • 定义访问接口为 /login 前段进行访问的接口为 /users/login
  • 获取前端传过来的登录信息(用户名和密码)get的接收方式为req.query,post的接收方式为req.body
  • 对获取到的密码进行加密,加密需要使用crypto模块
  • 对获取到的用户名与mongo数据库中log集合中的信息进行对比,用户名和密码是否相同,如果相同,返回成功信息,如果成功,返回失败信息
router.post("/login", function (req, res, next) {
  // let file = path.resolve(__dirname,"../public/json/loginData.json")
  // console.log(file)
  let name = req.body.username
  let pwd = req.body.password
  // 这个加密中的update里面信息和注册时写入的信息一样
  const hash = crypto.createHmac('sha256', pwd)
                   .update('hash')
                   .digest('hex');
  Info.find({username:name,password:hash}).then((response) => {
    if(response.length > 0){
      req.session.user = name
      res.json({
        status : 0,
        message:"用户登录成功,点击确定跳转登录界面",
        name:req.session.user
      })
    }else{
      res.json({
        status : -1,
        message:"登录失败,密码或者用户名错误"
      })
    }
  })
})
登录界面js代码

给提交按钮绑定点击事件,获取用户名和密码,然后传递给后台,根据后台返回的数据判断用户是否登录成功

$("#submit").on("click",function() {
            var username = $("#username").val()
            var password = $("#password").val()
            $.post("/users/login",{username,password}).then(res => {
                console.log(res)
                if(res.status === 0){
                    alert(res.message)
                    location.href = "./client.html?name=" + res.name
                }else{
                    alert(res.message)
                }
            })
        })
socket.io 通讯技术

接下来就是最重要的相互通讯技术的实现,需要socket.io 插件来实现,首先通过cnpm安装socket.io插件

cnpm i socket.io --save

然后在bin目录下的www文件的 var server = http.createServer(app);这句后面写以下代码

var io = require("socket.io")(server)
io.on('connection', (socket) => {
  socket.on("msg",(data) => {
  // 判断是否是用户,如果不是用户则将输入的信息存储为用户名
    if(!socket.user){
      socket.user = data
      io.emit("msg","欢迎"+data +"进入聊天室")
    }else{
      io.emit("msg",socket.user+"说:"+data)
    }
  })
  socket.on("disconnect",(data) => {
    socket.broadcast.emit("msg",socket.user+"因为受不了大家的摧残离开了聊天室")
  })
});

使用socket.io监听连接状态,然后对数据传过来的信息进行处理

socket.emit(信息段的名称,信息内容) // 只能传给一个用户看,其他用户看不到

io.emit(信息段的名称,信息内容) // 传给多个用户

socket.broadcast.emit(信息段的名称,信息内容) // 处理当前用户,其他用户都能看到
服务端图片接收

需要安装formidable插件和内置fs插件

cnpm i formidable --save
var fs = require("fs")
var formidable = require("formidable")

图片写入到public的upload文件夹内 代码存放在index.js里面

router.post("/upload",(req,res) => {
  var form = new formidable.IncomingForm();
  form.uploadDir ="./public/upload/"
  form.parse(req,function(err, fields,files){
    if(!files.BQ) return
    fs.renameSync(files.BQ.path,form.uploadDir+files.BQ.name)
    res.json({
      status:0,
      data:files.BQ.name
    })
  })
})
客户端进行信息传递
let name = location.search.split("=")[1]
        var socket = io('http://10.7.157.82:3000');
        $("#submit").on("click",function(){
            socket.emit("msg",$("#text").val())
        })
        // 上传图片
        $("#upload").on("click",function () {
            var form = new FormData()
            form.append("BQ",myFile.files[0])
            $.ajax({
                method:"post",
                url:"/upload",
                data:form,
                cache:false,
                contentType:false,
                processData:false
            }).then((res) => {
                console.log(res)
                let str = "<img src='../upload/"+res.data+"' />"
                socket.emit("msg",str)
            })
        })
        // 开局使用socket.io 向后台发送用户名
        socket.emit("msg",name)
        socket.on("msg",(data) => {
            $("#box").html(data+"<br />"+ $("#box").html())
        })

结语

这是我做的一个十分简单的聊天系统,有很多问题还没有解决,在后面的学习中我将会慢慢克服这些困难取得更大的进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值