本文采用Express作为服务端框架,通过配置Token、七牛云对象存储(存储图片、视频等)、后端跨域、MySQL持久化存储等实现一个完整的服务端流程
并将异步抽离MySQL查询,实现代码的Promise化
详见GitHub: https://github.com/cgq001/express-token
1.Token
//生成Token
npm install jsonwebtoken -S
// 登陆并生成token
Routers.get('/load', (req,res) => {
let tokenObj={ //携带参数
id: 1,
username: '小明'
}
let tokenKey = "123456455" //加密内容,随便写,但是最好存储在一个公共文件内,因为解密的时候也需要用
let token = jwt.sign(tokenObj,tokenKey,{
expiresIn: 60*60*24 // token时长
})
res.json({ //返回前端
code: 0,
msg: '查询成功',
token:token,
data:{
username: '12456'
}
})
})
//验证Token
npm install express-jwt -S
//token/index.js
const expressJwt = require('express-jwt');
const { secretKey } = require('./constant'); //存在 公共文件里的 加密内容即为生成Token时的加密内容(如上:tokenKey="123456455" )
const jwtAuth = expressJwt({secret: secretKey}).unless({path:['/index/load']})
//unless 为排除那些接口,排除的接口将不再进行Token 验证
module.exports = jwtAuth;
//验证
// 全局验证Token是否合法
const tokens = require('../token/index')
Routers.use(tokens)
//注意 这里可以配置在特定的路由文件内,不要配置到app.js(全局入口文件),毕竟不需要验证Token 的文件如果很多的话,不能一个一个去排除吧?
前端携带Token
Authorization: "Bearer xczsxssdshsd.zxjjdjsjdsjdsjsd.djjsjsjsdj"
2.七牛云对象存储
七牛云为常用的对象存储空间,每个人都有10G的免费使用空间,这点还是很良心的,一般个人使用的话,也够用了,自行注册,配置
插件支持
npm install formidable -S # 获取上传文件
npm install qiniu -S # 七牛云SDK
const moment = require('moment'); // 获取格式化时间
var path = require('path')
const fs = require('fs')
//获取图片等文件
var formidable = require('formidable');
//七牛云配置
const qiniu = require('qiniu')
const accessKey = '*********' //AK 注册后 可在后台获取
const secretKey = '*********' //SK 祖册后 可在后台获取
const bucket = 'book' // 上传到的对象存储名称(创建对象存储的时候起的名字)
// 七牛云 上传
Routers.post('/upload', (req,res) => {
let form = new formidable.IncomingForm();
form.parse(req, function (err, fields, filesa){
console.log(filesa.file); //获取上传后的文件 filesa.file(file是上传时的Name名字)
let MathRoundNumber = Math.round(Math.random()*100000)
let MathRound = moment().format("YYYY_MM_DD_hh_mm_ss")
let key = MathRound+MathRoundNumber+filesa.file.type //上传 后文件的名字(相当于对上传后文件进行重命名)
let path= filesa.file.path //上传文件路径
let mac = new qiniu.auth.digest.Mac(accessKey,secretKey)
let options = {
scope: bucket,
expires: 3600 * 24 //凭据过期时间
}
let putPolicy = new qiniu.rs.PutPolicy(options)
let uploadToken = putPolicy.uploadToken(mac)
uploadFile(uploadToken, key, path).then(idea=>{
console.log('上传成功');
res.json({
code: 0,
msg: '上传成功',
data:{
url: "http://img.abc.com/"+idea.key
//上传返回的是文件名称,需要搭配上自己在对象存储内绑定的域名(七牛云赠送的域名只能使用一个月)
}
})
})
.catch(err=>{
//其实这种情况 也上传了图片,为了严禁起见
if(err.key){
res.json({
code: 4,
msg: '上传失败',
data:{
url: "http://img.abc.com"+err.key
}
})
}else{
res.json({
code: 4,
msg: '上传失败',
data:{
url: ''
}
})
}
})
//构造上传函数
async function uploadFile(uptoken, key, localFile) {
var config = new qiniu.conf.Config();
// 空间对应的机房
config.zone = qiniu.zone.Zone_z0;
var formUploader = new qiniu.form_up.FormUploader(config);
var putExtra = new qiniu.form_up.PutExtra();
return new Promise((resolve,reject)=>{
// 文件上传
formUploader.putFile(uptoken, key, localFile, putExtra, function(respErr,
respBody, respInfo) {
if (respErr) {
throw respErr;
}
if (respInfo.statusCode == 200) {
resolve(respBody)
} else {
reject(respBody) //其实这种情况 也上传了图片,为了严禁起见
}
})
})
}
})
})
3.跨域
npm install cors -S
// 配置跨域
app.use(cors());
4.MySQL
1.MySQL连接处
npm install mysql -S
// 引入 mysql 数据库连接依赖
const mysql = require("mysql");
//config/db.js
// 创建 mysql 连接池并配置参数
const pool = mysql.createPool({
host: "127.0.0.1", // 主机地址
port: 3306, // 端口
user: "root", // 数据库访问账号
password: "*****", // 数据库访问密码
database: "im", // 要访问的数据库
charset: "UTF8_GENERAL_CI", // 字符编码 ( 必须大写 )
typeCast: true, // 是否把结果值转换为原生的 javascript 类型
supportBigNumbers: true, // 处理大数字 (bigint, decimal), 需要开启 ( 结合 bigNumberStrings 使用 )
bigNumberStrings: true, // 大数字 (bigint, decimal) 值转换为javascript字符对象串
multipleStatements: false, // 允许每个mysql语句有多条查询, 未防止sql注入不开启
//connectTimeout: 5000, // 数据库连接超时时间, 默认无超时
});
// console.log(pool);
pool.connectionLimit = 10; // 连接池中可以存放的最大连接数量
pool.waitForConnections = true; // 连接使用量超负荷是否等待, false 会报错
pool.queueLimit = 0; // 每个连接可操作的 列数 上限, 0 为没有上限
// 对外暴漏从连接池中获取数据库连接的方法
exports.query = function(sql, arr, callback){
//建立链接
pool.getConnection(function(err,connection){
if(err){throw err;return;}
connection.query(sql,arr,function(error,results,fields){
//将链接返回到连接池中,准备由其他人重复使用
connection.release();
if(error) throw error;
//执行回调函数,将数据返回 callback &&
callback && callback(results,fields);
});
});
};
4.2 异步查询
//user.js
//数据库配置
const db= require('../config/db')
const fn={
// 登录
loadUser:async function(data){
let sql ="select * from user where email=?"
let arr=[]
arr.push(data)
return new Promise((resolve,reject)=>{
db.query(sql,arr,function(data,err){
if(err){
reject(err)
}
resolve(data)
})
})
// return await db.query(sql,arr)
},
// 获取好友列表
getUserlist:async function(id){
let sql ="select a.*, b.*,a.id as user_id from contacts a inner join user b on a.userlistid = b.id where userid=?"
let arr=[]
arr.push(id)
return new Promise((resolve,reject)=>{
db.query(sql,arr,function(data,err){
if(err){
reject(err)
}
resolve(data)
})
})
}
}
module.exports = fn;
1.3使用
const fn = require('../model/user') //获取 异步查询方法
//获取好友列表
Routers.post('/getUserList', (req,res) => {
console.log(req.user);
fn.getUserlist(req.user.id)
.then(ideas=>{
res.json({
code: 0,
data: ideas
})
})
})
5.静态文件
// 配置静态目录
app.use(express.static(path.join(__dirname,'public')))
网友评论