阿里云 后台及接口 归档 nodejs

本文档作为归档。
一个项目分为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
前端
|----小程序
|----移动端webapp
|----PC端 webapp
接口(连接前端,后端和数据库)
|----云函数
|----Bmob 云函数
|----Leancloud 云函数
|----Aliyun 云函数
|----nodejs express框架
后端
|----管理后台(PC web端 nodejs编写)
|----Leancloud云引擎
|----GitHub page
|----阿里云centos nginx
数据库
|----Bmob云存储
|----Leancloud云存储
|----Mongodb
|----阿里云存储
|----图 片
|----七牛云(需要绑定一个备过案的域名,个人的也行)
|----阿里云oss
|----Bmob 素材

管理后台

使用 nodejs + vue + elementUI

目前nodejs最完善的管理后台,25000多star,gihub地址:https://github.com/PanJiaChen/vue-element-admin。
修改完后,生成的文件在 dist 文件夹内。不管是扔到leancloud的网站托管,还是github page,还是自己搭建一个nginx服务器,上传的其实都是dist文件夹里的内容

Leancloud 网站托管(云引擎):

好处是:上线快,可以用他们的二级域名
缺点是:性价比低,文档差

  1. 在lean cloud后台新建一个应用,记得设置域名,如 myproject.leanapp.cn
  2. 在本地电脑下载leancloud的nodejs上传框架(express)
  3. 把dist文件夹里生成的内容扔到框架里的public文件夹里
  4. lean switch 选择新建的那个应用
  5. lean deploy (第一次如果不成功,就多试几次)
  6. 如果是付费的标准环境,lean publish
  7. 访问时可用 projectname.leanapp.cn 来访问

Github page

好处是:免费,可以用他们的二级域名
缺点是:国外服务器,真tm叫一个慢。可人家免费阿。自己做blog还行

阿里云自建 nginx 服务器

  1. 去阿里云买一个服务器
    a) 可以买个ECS (预装操作系统centos 7.3),缺点是什么都得自己装,优点是想装什么装什么
    b) 轻量应用服务器 (选择nodejs),优点是默认的都装好了,而且因为是套装所以比ECS便宜,缺点是版本太老,自己还得更新
    c) 哪个便宜买哪个,有时会有活动。无非就是苦点累点自己重新搭系统。
  2. 安装 nginx
  3. 完成后找到 /etc/nginx/nginx.conf 这个文件,修改里面的部分参数。
    注1:使用 xftp 工具找这个文件,并拖动到左侧桌面编辑,不容易出错
    注2:敲命令用 xshell 工具
    需要修改的参数为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
      server 
    {
    listen 80; // 80端口直接打开
    server_name 120.79.208.***; // ip地址
    root /var/www/myproject; // 目录,随便什么都行

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    location / {
    root /var/www/myproject; // 目录
    index index.html; // index.html
    }

    error_page 404 /404.html;
    location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
    }

    以上几个参数极为重要。目录,端口,ip千万别错

  4. 修改完后用 xftp 拖回服务器,覆盖原nginx.conf
    注:如果使用的是轻量应用服务器,nginx.conf在另一个目录,/usr/local/nginx/nginx.conf 可别改错了
    nginx.conf 这个文件是告诉服务器,如果有人访问 120.79.208.***:80端口,则打开 /var/www/myproject 文件夹下的 index.html 文件。而这个index.html 文件就是 dist 文件夹下的index.html。
  5. 把 dist 文件夹下生成的文件都用 xftp 扔到 /var/www/myproject 目录下去
  6. 也是最重要的一步,一定要去阿里云的安全控制组里把 80 端口打开,而且是双向。不同厂家的不同版本的服务器默认打开的端口是不一样的,一定要检查。
    好几次都是因为端口的问题导致没打开。
  7. 记得重启系统
    /usr/local/nginx/sbin/nginx -s reload
  8. 在浏览器里输入 IP地址,只要阿里云安全组里端口打开了,基本网页就打开了。
  9. 用一个域名指向这个IP地址。
    注:如果服务器是国内服务器,则域名需要备案,否则指向后会打不开;如果服务器是国外的,那无所谓

接口

利用后端云

后端云的优势在于上线速度快,可以实现数据库存储,云函数,验证,短信等多种功能。适用于小型应用。
切记,免费版只是自己验证用。如果客户量大,使用频率高的正式版必须联系他们进行付费,只要付钱,他们会进行服务器迁移,甚至专线,别说并发,几百的ddos都能挡。
我用过的后端云有Leancloud, Bmob。知晓云也出了,只是因为刚出,所以不太敢用,毕竟迁移风险太大(主要是懒)。
不管谁家的,数据库和云函数配合着使用。另外,每一家或许是经费有限,很多文档都更新不及时,需要自己摸索。

Bmob

  1. 数据库里新建自己的表格(不展开)
  2. 云函数
    a) 常用几种用法如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    function onRequest(request, response, modules) {    
    var db = modules.oData;
    var objectId = request.body.objectId; // 获取传入参数
    var functions = modules.oFunctions; // bmob云函数调用另一个bmob云函数

    db.findOne({
    "table":"TestMenu1",
    "objectId":objectId //记录的objectId
    },function(err,data){

    var http = modules.oHttp;

    var options = {
    "url": 'http://120.79.208.***:7088/print_post',
    "headers": {
    'Content-Type': 'application/x-www-form-urlencoded' // 注意,易联云打印机 application/x-www-form-urlencoded
    },
    "body": "machineCode=" + machineCode + "&originId=" + objectId + "&content=" + printtext // 注意,不要有&字符,否则会被截断
    }

    http.post(options, function(error, res, body) { // 通过bmob调用post请求
    var result3= JSON.parse(body);
    db.insert({ // 插入一行
    "table":"log",
    "data":{"name": result.nickName, "info":body, "function": 'ylyPrintBmob'}
    },function(err,data){
    response.send("insert success");
    });
    db.update({ // 更新
    "table":"TestMenu1",
    "objectId":objectId,
    "data":{"Payorder":payorder}
    },function(err,data){
    response.send("update success");
    });

    });

    });
    }

    b) 关于表中的条件搜索,bmob文档更新不及时,类似如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    db.find({
    "table":"_User", // 表名
    "key":"star,auditTimes", // 返回字段列表,多个字段用,分隔
    "where":{"objectId":{"$in":fathers}}, // 查询 objectId 在字段 fathers 中
    //"where":{"objectId":{"$in":['13017cc421','5b0edfcffb','4b09ab97de','72a1772287']}},
    // 以上查询 objectId 在数组 ['13017cc421','5b0edfcffb','4b09ab97de','72a1772287'] 中的
    //"where":{"c":{"$ne":1}}, // 条件查询 查询c字段值不为1的记录
    //"order":"-a,b", // 排序列表,[-]字段名称,-表示降序,默认为升序
    //"limit":10, // limit大小,一页返回多少条记录,默认为0
    "count":1 // count,只返回符合条件的记录总数
    },function(err,data){

    });

    // 以下功能为将符合条件的结果的 firstLayerNum 数值求和!!
    db.find({
    table: '_User',
    sum: 'firstLayerNum',
    where: {
    fathers: myUserId, // fathers中有myUserId
    "star":{"$ne": "0"} // 同时 star不为0
    }, //
    /*where: {
    '$or': [ // 或
    {fathers: myUserId}, // fathers中有myUserId
    {objectId: myUserId} // 或者 objectId 为myUserId
    ]
    },*/
    //where:{"star":{"$ne": "1"}},
    }, function(err, data){

    });

Leancloud

用法与Bmob类似,最初用的是Leancloud,后来迁到 Bmob,主要是Leancloud总是感觉各种诡异的不稳定,实在是鄙人能力有限解决不了……

Node express 框架自己写

  1. 买个阿里云服务器,预装centos 7.3或以上稳定版本
  2. 安装nodejs,注意版本,装最新的稳定版
  3. 安装express
    npm install express-generator -g
    安装完后,记得用 express 命令试一下。如果始终express命令不存在,建议重装nodejs
  4. 使用创建 Express 框架创建项目命名为 myapp
    express myapp
  5. 给myapp安装一些插件
    body-parser - node.js 中间件,用于处理 JSON, Raw, Text 和 URL 编码的数据。
    cookie-parser - 这就是一个解析Cookie的工具。通过req.cookies可以取到传过来的cookie,并把它们转成对象。
    multer - node.js 中间件,用于处理 enctype=”multipart/form-data”(设置表单的MIME编码)的表单数据。

    1
    2
    3
    $ cnpm install body-parser --save
    $ cnpm install cookie-parser --save
    $ cnpm install multer --save
  6. 安装日志插件 log4js

    1
    npm install log4js
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 以下为日志处理模块
    const log4js = require('log4js');
    log4js.configure({
    appenders: { cheese: { type: 'file', filename: 'cheese.log' } }, // 日志输出在 cheese.log 文件夹下
    categories: { default: { appenders: ['cheese'], level: 'info' } } // 注意这个level,只保存info及下方的 warn, error, fatal
    });
    const logger = log4js.getLogger('cheese');
    /*logger.trace('Entering cheese testing');
    logger.debug('Got cheese.');
    logger.info('Cheese is Comté.'); // 保存
    logger.warn('Cheese is quite smelly.'); // 保存
    logger.error('Cheese is too ripe!'); // 保存
    logger.fatal('Cheese was breeding ground for listeria.'); // 保存 */
    // 以上为日志处理模块
  7. 安装定时器模块
    安装
    npm install node-schedule --save 或者 yarn add node-schedule

    用法
    1、Cron风格定时器
    const schedule = require('node-schedule');

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    // 以下为定时执行,刷新token
    var tokenData = {
    'accessToken' : '',
    'refreshToken' : '',
    'machineCode': '',
    };

    ...

    const schedule = require('node-schedule');
    const scheduleCronstyle = ()=>{
    //每月的1日1点1分30秒触发,更新一次密钥:
    schedule.scheduleJob('30 1 1 1 * *',()=>{
    console.log('scheduleCronstyle:' + new Date());
    logger.info('定时执行密钥刷新');
    oauthClient.getToken().then(function (res){
    if (
    res.error != 0 &&
    res.error_description != 'success'
    ) {
    throw new Error('failed:' + res.error_description);
    }
    tokenData.accessToken = res.body.access_token;
    tokenData.refreshToken = res.body.refresh_token;
    // console.log('更新后的密钥为', res);
    logger.info('更新后的密钥为' + JSON.stringify(res));
    // console.log('存储后的密钥为', tokenData);
    logger.info('存储后的密钥为' + JSON.stringify(tokenData));
    });
    });
    }
    scheduleCronstyle();
    // 以上为定时执行,refresh token
    1
    2
    3
    4
    5
    6
    每分钟的第30秒触发: '30 * * * * *'
    每小时的1分30秒触发 :'30 1 * * * *'
    每天的凌晨1点1分30秒触发 :'30 1 1 * * *'
    每月的1日1点1分30秒触发 :'30 1 1 1 * *'
    2016年的1月1日1点1分30秒触发 :'30 1 1 1 2016 *'
    每周1的1点1分30秒触发 :'30 1 1 * * 1'
  8. 启动模块测试
    在express框架生成后的myapp文件夹下有个express.js,内容大致如下。表示express.js将监听7088端口号,同时收到print请求时会返回字符串 ‘新的请求……’

    1
    2
    3
    4
    5
    6
    7
    8
    9
    app.get('/print', function (req, res) {
    res.send('新的请求......');
    console.log("新的请求......")
    })
    var server = app.listen(7088, function () {
    var host = server.address().address
    var port = server.address().port
    console.log("成功啦成功啦,访问地址为 http://%s:%s", host, port)
    })

    直接执行以下命令,即可启动,并用外网访问IP地址以及端口号时可以看到返回的字符串 ‘新的请求……’
    node express.js
    注:当使用外网ip访问此端口号时,如在浏览器内直接输入 http://120.79.208.***:7088/print, 如果没有反应,先检查阿里云服务器安全组内该端口号有没有开。
    阿里云不同的服务器默认打开的端口都不一样,包括80端口都需要检查。确保双向打开。

  9. 安装 forever 模块
    使用 node express.js 启动的进程在推出 xshell 之后就会自动关闭,所以需要使用 forever 启动进程,即使退出控制台也能继续执行下去。
    // 如果没有forever,就安装。记得加-g,forever要求安装到全局环境下
    $ sudo npm install forever -g
    启用进程
    1
    2
    $ cd myapp
    $ forever start ylyPrint.js

图片服务器

七牛云

由于监管越来越严,七牛云的图片存储需要绑定备过案的域名,不能再像以前一样,使用七牛分配的域名了。这点很重要。只要是备过案的就行,无所谓企业备案还是个人备案。
1) vue中图片上传可使用elementUI封装的 el-upload 控件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<el-upload
:data="dataObj" // dataObj: { token: '', key: '0127.jpg' },
:multiple="false"
:before-upload="beforeAvatarUpload" // 传之前做的事
:on-preview="handlePreview"
:on-remove="handleRemove"
:on-success="handleSuccess" // 传完后做的事,如拼接并保存图片名字
:file-list="fileList2" // 图片列表
action="https://upload.qiniup.com" // 七牛接受直传的api地址
class="upload-demo"
list-type="picture-card"> // el-upload 空间的样式
<el-button size="small" type="primary">點擊上傳</el-button>
<div slot="tip" class="el-upload__tip">只能上傳jpg/png文件,且不超過5M</div>
</el-upload>

2) handleSuccess()
由于七牛云上传成功后返回的只有图片在空间里的name,所以图片的路径需要自己拼接后保存。 如:http://ttkk.com/myimage.jpg
1
2
3
4
5
6
7
8
handleSuccess(response, file, fileList) {
// console.log('fileList=', fileList)
this.fileList2.push({ // 把新图片push 到当前图片列表中
name: response.key, // response.key 是图片在七牛的name
url: 'http://' + this.qiniuaddr + '/' + response.key // 拼接
})
// console.log('filelist2=', this.fileList2)
},
3) beforeAvatarUpload() 在上传之前,需要给 dataObj 传两个参数,一个是文件名给到key,一个是token给到token。这两个对了就基本没问题了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
beforeAvatarUpload(file) {
console.log('beforeAvatarUpload')
this.dataObj.key = file.name
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 5
if (!isJPG) {
return this.$message.error('上传文件只能是 JPG或PNG 格式!')
}
if (!isLt2M) {
return this.$message.error('上传图片大小不能超过 5MB!')
}
var token = getToken() // getToken 函数去 qiniu.js 里找,里面需要输入用户的id和密钥
console.log('token=', token)
this.dataObj.token = token
},
坚持原创技术分享,您的支持将鼓励我继续创作!