express 基础

文章目录

模板

项目模板下载 express_token

git clone https://gitee.com/weixijin_177/express_moban.git

项目模板下载 express_session

git clone https://gitee.com/weixijin_177/express-session-service.git

express框架的特性

优点
路由定义更简单
http请求参数的简化处理
对模板引擎支持度高,更容易渲染页面
提供了中间件,更易处理http请求
功能更好扩展

express搭建一个简单的路由

const express = require("express")

//创建网站服务器
const app = express()

app.get("/", (req, res) => {
    res.send("hello")
})
app.get("/list", (req, res) => {
    res.send("<h1>你好</h1>")
})

app.listen(3000, () => {
    console.log("创建成功")
})

中间件

可以在错误处理中间件中可以进行日志打印收集

中间件的应用

404 处理 表示没有接口可以匹配 放在所有路由后面

app.use((req, res, next) => {
    res.status(404).json({
        code: 404,
        msg: "没有api可以匹配"
    })
})

错误日志 和 500

//错误请求的处理这个必须在后面
// 这儿的错误数据 来源于具体的路由的 catch(err){ next(err) }

app.use((err, req, res, next) => {
    err=JSON.parse(err)
    err.time=new Date().Format("yyyy-MM-dd hh:mm:ss")
    err=JSON.stringify(err,null,"  ")
    // 错误日志收集
    fs.appendFile("./data/err.txt","\n"+ err, (err, data) => {
        if (err) {
            return res.json({
                msg: util.format(err)
            })
        }
    })
    res.status(500).json({
        code: 500,
        msg: util.format(err)
    })
})

模块化路由

const express = require("express")

const app = express() //创建网站服务器

//引入路由模块
const login = require("./code/login")
const admin = require("./code/admin")

//为路由匹配路径
app.use("/login", login)  //当以/login开始的,接下来就去login.js中,去看匹配路径
app.use("/admin", admin)

app.listen(3000, () => {
    console.log("开启成功")
})

**login.js**
const express = require("express")

const login = express.Router() //创建路由

login.get("/index", (req, res) => {  //必须要先匹配到/login ,才能来这儿
    res.send("登陆页面")
})
module.exports = login

设置cors 跨域

var express = require('express');  
var app = express();  
//设置CORS
app.all('*',function (req, res, next) {
    res.header('Access-Control-Allow-Origin','http://localhost:3001'); //当允许携带cookies此处的白名单不能写’*’
    res.header('Access-Control-Allow-Headers','content-type,Content-Length, Authorization,Origin,Accept,X-Requested-With'); //允许的请求头
    res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT'); //允许的请求方法
    res.header('Access-Control-Allow-Credentials',true);  //允许携带cookies
    next();
});

app.get('/', function(req, res) {  
    res.send("你已经成功访问该服务器");  
});  
app.listen(3000);

请求类型

get post put(全部更新) patch(局部更新) delete
设置响应状态码
res.status(200).send()

参数获取

几种形式
? query
/:id params
post请求 body

使用get,delete方法完成表单提交
req.query

使用post,put方法完成表单提交
req.body

post,put和表单提交需要下面插件
安装插件

cnpm install body-parser --save

具体配置

var bodyParser=require("body-parser") //引入

//配置body-parser插件
app.use(bodyParser.urlencoded({extended:false}))//这是解析表单的
app.use(bodyParser.json())    //这是解析json格式的 

定义一个全局变量

方式一

1.定义
let sort = 5000
app.listen(sort, () => {
    global.initUrl = __dirname
    console.log(`http://127.0.0.1:${sort}   开启成功`)
})
2.使用  (js)
    let oldurl1 = global.initUrl + `/public/${oldurl}`

方式二

  //    默认登陆 后保存用户信息 到全局
           res.app.locals.userdata={
            name:"张三",
            age:18,
            sex:"男"
        }
        res.render("mob/index",{
            title:"baike手机"
        })

html
<body>

    {{if userdata}}
    {{userdata.name}}
 
    {{else if userdata==null}}
        未登陆
    {{/if}}
    <h1>
        mobile
    </h1>
</body>

方式三

在中间件中绑定给req一个全局变量,后续都能直接使用

静态资源的处理

const express = require("express")
const path = require("path")
const app = express()
    //第一个参数表示必须以此开头,第二个表示开放的路径
app.use("/public", express.static(path.join(__dirname, "public")))

app.get("/index", (req, res) => {
    res.send()
})

app.listen(3000)

实际访问

http://127.0.0.1/img/1.jpg       // 不用加/public

利用一个接口返回不同的图片

// 利用一个接口返回不同的图片

app.get("/randomImg",(req,res)=>{
    // json返回
    if(req.query.type){
      return  res.send("https://tse1-mm.cn.bing.net/th/id/OIP.hQhMO0Vs5v9TCl581A5QaQHaJQ?pid=ImgDet&rs=1")
    }
    // 直接重定向地址,img src直接可以使用
    res.redirect("https://tse1-mm.cn.bing.net/th/id/OIP.hQhMO0Vs5v9TCl581A5QaQHaJQ?pid=ImgDet&rs=1")
})

res.send/json和res.render

send 直接发送数据
json 发送json数据
render 发送需要传送模板字符的数据

一些常用的模块

密码加密

1.创建一个文件crypto.js ,位置任意

const crypto = require('crypto');

var setCrypto=(info)=>{
    return crypto.createHmac('sha256', "secret")    //secret 可以修改,是个额外的加密串
                    .update(info)
                    .digest('hex');  //表示16
}

module.exports={
    setCrypto
}

2.具体的使用

var {setCrypto}=require('../mod/crypto.js')

//具体使用,注意在登陆时也需要对传入的数据进行一次加密,再比较
password=setCrypto(password)

发送验证码部分

1.在mail.js

 "use strict";
const nodemailer = require("nodemailer");

// 创建发送邮件的对象
  let transporter = nodemailer.createTransport({
  service: 'qq', // 使用了内置传输发送邮件 查看支持列表:https://nodemailer.com/smtp/well-known/
    port: 465, //端口号
    secure: true, // true for 465, false for other ports
    auth: {
      user:'1925541533@qq.com',   //发送方
      pass: 'qvhitkhzihnabbcb',  
    }
  });

  function sendmail(mail,code){
      // 邮件信息
      let  mailObj={
        from: '"hello" <1925541533@qq.com>', // sender address
        to: mail, // list of receivers
        subject: "注册验证", // Subject line
        text: `您的验证码是${code},有效期五分钟`, // 文字信息
        //html: "<h2 style=”color:red”>Hello world?</h2>" // html信息
      }
      return new Promise((resolve,reject)=>{
        transporter.sendMail(mailObj,(err,data)=>{
            if(err){
              reject(err)
            }else{
              resolve(data)
            }
        });
      })
      
  }
  module.exports={sendmail}

2.在相关的模块中导入

 const Mail=require("../utils/mail.js")

//发送验证码部分
login.get('/postmail',async (req,res)=>{
    let {email}=req.query
    let code1=parseInt(Math.random()*10000)
    let data1=await Mail.sendmail(email,code1)
    codes.code=code1
    res.send({status:200,message:"ok"})
    
})

上传图片

base64的方式上传图片

前端
// 参数
// 1. 被点击的节点 class
// 2. 需要隐藏的节点 class
// 3. 图片要放置的父节点 class

function collectImg(ele1, ele2, ele3) {
    return new Promise((res, rej) => {     // 这儿必须要加这个异步
        var v = $(ele1).val();
        var reader = new FileReader();
        reader.readAsDataURL($(ele1)[0].files[0]);	 // 只选中了一个文件,如果多个需要循环

        // 获取原来文件名
        let oldfilename = $(ele1)[0].files[0].name || ''
        strs = v.split('.');
        var suffix = strs[strs.length - 1];
        // 判断文件格式
        if (suffix != 'jpg' && suffix != 'gif' && suffix != 'jpeg' && suffix != 'png') {
            Message("你选择的不是图片,请选择图片!", 'error');
            var obj = document.getElementById('fileup');
            obj.outerHTML = obj.outerHTML; //这样清空,在IE8下也能执行成功
            return false
        }
        // 判断文件的大小 小于2M
  
        if($(ele1)[0].files[0].size/1000>2*1024){
            Message("上传文件不能大于2M",'error')
            return false
        }
        reader.onload = function (e) {
            if (ele2 !== null) {
                $(ele2).hide()
            }
            $(ele3).empty();
            let img1 = `
                            <img class="userheader" src="${e.target.result}" alt="">`
            $(ele3).append(img1)
            // res({
            //     imgdata:e.target.result,
            //     oldfilename
            // })
            res(e.target.result)
        };
    })
}

   $.ajax({
            type:"post",
            url:"http://127.0.0.1:5000/admin/work/ceshi",
            data:object,	// json数据
            success:(data)=>{
                console.log(data)
            }
        })

后端

// 专门用于处理 前端传过来的 base64格式图片

function base64Company(imgData,basename){
    return new Promise((resive,reject)=>{
    //过滤data:URL
    let base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
    let dataBuffer = Buffer.from(base64Data, 'base64');
    // 处理名字  这儿的路径不是相对路径 为固定写法 (绝对路径)
    let filename= `./public/uploads/${Date.now()} + ${basename}.png`
    fs.writeFile(filename, dataBuffer, function (err) {
        if (err) {
            reject(err)
        } else {
          resive("ok")
        }
    });
    })
}

// 这个是测试接口

work.post('/ceshi', async (req, res) => {
    // console.log(req.body)
    //接收前台POST过来的base64
    let { company_3_3, company_id_3_2, certificates_3_3, userheader_register3_3 } = req.body
    base64Company(certificates_3_3,'certificates_3_3')
    res.json({
        data: req.body
    })
})

单独上传一张图片

前端处理

<template>
  <div class="formfile">
    <input
      type="file"
      ref="uploadheaderimg"
      name="headerurl"
      value="单文件上传图片"
      @change="handleImg"
    />
  </div>
</template>

<script>
import { putHeaderImg } from "@/api/data";
export default {
  methods: {
    async handleImg(e) {
      var file = e.target.files[0];
      var param = new FormData();
// 如果需要提交其他的参数
     // param.append("_id", this.$store.state.userdata._id);
     // param.append(this.$refs.uploadheaderimg.name, file, file.name);

      param.append(this.$refs.uploadheaderimg.name, file, file.name);
      let data = await putHeaderImg(param);
    },
  },
};
</script>

// 用户头像上传 api
function putHeaderImg(data) {
    return http({
        url: "/putHeaderImg",
        method: "Post",
        data,
        headers: {
            'Content-Type': 'multipart/form-data'
        }
    })
}

后端处理

cnpm install --save multer		//开放静态资源
const express = require("express")
const multer = require("multer")
const files = express.Router() //创建路由

//图片上传部分
// 新建一个仓库
var storage = multer.diskStorage({
    //设置上传后的文件路径
    destination: function (req, file, cb) {
        cb(null, './public/uploads/')
    },
    //给上传文件重命名,以防命名重复
    filename: function (req, file, cb) {
        cb(null, `${Date.now()} + ${file.originalname}`)
    }
})
// 配置一个接收器,用于使用仓库
var upload = multer({
    storage: storage
})
// 单名称单文件上传   single   headerurl 必须和前端提交的name一致   
// 单名城多文件    array
// 多名称多文件       fields   upload.fields([{name:'logo'},{name:'headerimg'}])     
files.post("/putHeaderImg", upload.single("headerurl"), async (req, res) => {
    let url = req.file.filename   //单文件上传  req.file  ;  多文件上传  req.files
    res.json({
        code: 200,
        data: {
            url: `uploads/${url}`
        }
    })
})
module.exports = files

带图片的表单提交

前端

<template>
  <div class="formfile">
    <form action="">
      <img v-if="headerimg" :src="headerimg" alt="" />
      <input
        type="file"
        ref="uploadheaderimg"
        name="headerurl"
        value="单文件上传图片"
        @change="handleImg"
      />
      <input type="email" name="email" v-model="emailval" />
      <button @click="handleChange">提交</button>
    </form>
  </div>
</template>

<script>
import { putHeaderImg } from "@/api/data";
export default {
  data() {
    return {
      headerimg: "", // 在页面预览的base64图片数据
      emailval: "",
      file: "", // 最终提交到后端的图片信息
    };
  },
  methods: {
    // 最终的表单提交
    async handleChange() {
      var param = new FormData();
      param.append(this.$refs.uploadheaderimg.name, this.file);
      param.append("email", this.emailval);
      let data = await putHeaderImg(param);
    },
    // 上传图片,保存图片信息
    handleImg(e) {
      var file = e.target.files[0]; // 拿到图片信息
      if (file) {
        this.file = file;
        // 选中了一张新的图片
        let fd = new FileReader(); // 本地预览
        fd.readAsDataURL(file); // 将图片信息解析成base64
        fd.onload = () => {
          if (fd.result.startsWith("data:image")) {
            // 选中的是一张图片
            this.headerimg = fd.result; // 预览
          } else {
            alert("你选择的不是一张图片");
          }
        };
      } else {
        return;
      }
    },
  },
};
</script>


// 用户头像上传
function putHeaderImg(data) {
    return http({
        url: "/putHeaderImg",
        method: "Post",
        data,
        // headers: {        // 这个可以没有
        //     'Content-Type': 'multipart/form-data'
        // }
    })
}

后端

const express = require("express")
const multer = require("multer")
const files = express.Router() //创建路由

//图片上传部分
// 新建一个仓库
var storage = multer.diskStorage({
    //设置上传后的文件路径
    destination: function (req, file, cb) {
        cb(null, './public/uploads/')
    },
    //给上传文件重命名,以防命名重复
    filename: function (req, file, cb) {
        cb(null, `${Date.now()} + ${file.originalname}`)
    }
})
// 配置一个接收器,用于使用仓库
var upload = multer({
    storage: storage
})
// 单名称单文件上传   single     
// 单名城多文件    array
// 多名称多文件       fields   upload.fields([{name:'logo'},{name:'headerimg'}])     
files.post("/putHeaderImg", upload.single("headerurl"), async (req, res) => {
    console.log(req.body.email)  //能拿到
    let url = req.file.filename   //单文件上传  req.file  ;  多文件上传  req.files
    res.json({
        code: 200,
        data: {
            url: `uploads/${url}`
        }
    })
})
module.exports = files

跨域(cors)

https://www.expressjs.com.cn/en/resources/middleware/cors.html

代理

https://www.bilibili.com/video/av86253852?p=34

node操作mysql

let mysql=require("mysql")

let con=mysql.createConnection({
    host:'localhost',
    user:"root",
    password:"root",
    //数据库名
    database:"book"
})
con.connect((err)=>{
    if(err){
        console.log(err)
    }else{
        console.log("连接成功")
    }
})

express 生成验证码

cnpm install --save svg-captcha

const express = require("express")
var svgCaptcha = require('svg-captcha');
const captcha = express.Router() //创建路由

captcha.get("/", (req, res) => {  //必须要先匹配到/captcha ,才能来这儿
    var codeConfig = {
        size: 4,// 验证码长度
        ignoreChars: '0o1i', // 验证码字符中排除 0o1i
        noise: 2, // 干扰线条的数量
        height: 44 
    }
    var captcha = svgCaptcha.create(codeConfig);
    //存session用于验证接口获取文字码
    //需要时通过req.session.captcha 调用
    // req.session.captcha = captcha.text.toLowerCase(); 
    process.env.captcha = captcha.text.toLowerCase();  //挂载到全局
    var codeData = {
        imgurl:captcha.data,
        state:200
    }
    res.send(codeData);
})
module.exports = captcha

express生成token

cnpm install jsonwebtoken --save 

express生成session

cnpm install --save express-session

express–md5 加密

对数据进行加密

express–https
对通信信道进行加密

数据验证(express-validator)

基本使用
1.安装

cnpm install --save express-validator

2.导入

const { body,param,query,validationResult } = require('express-validator');  // 分别用于处理body提交; /:id 动态路由;?name="wxj"提交

3.使用

user.post("/register", 
[
  body('password',"密码长度最小5").isLength({min:5}),
],
(req,res,next)=>{
  const errs=validationResult(req)
  if(!errs.isEmpty()){
    return res.status(400).json({
      err:errs.array()
    })
  }
  next()
},
async (req, res) => {}

常用的校验

body('password',"密码长度最小5").isLength({min:5})	// 字符长度  
check('email').isEmail(),		// 非空
isMobilePhone()		// 手机号

随机字符的生成

uuid

常用方法

ToJSON() // 用于将查询出来的mongo对象转化为正常对象

上一篇:Express三大内置中间件


下一篇:python 字典的一些简单操作