美文网首页
Node开箱即用的服务端基本配置

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

作者: 大菜鸟呀 | 来源:发表于2019-12-20 16:57 被阅读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')))
    

    相关文章

      网友评论

          本文标题:Node开箱即用的服务端基本配置

          本文链接:https://www.haomeiwen.com/subject/ilvspctx.html