Node开箱即用的服务端基本配置

2019-12-20  本文已影响0人  大菜鸟呀

本文采用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')))
上一篇下一篇

猜你喜欢

热点阅读