文章目录
模板
项目模板下载 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对象转化为正常对象