美文网首页前端那些事
利用node 一键部署静态资源到 七牛

利用node 一键部署静态资源到 七牛

作者: iwhao | 来源:发表于2019-07-31 13:41 被阅读0次

    利用node.js 一键部署七牛

    前期准备 环境配置

    element

    node (我的版本 v8.11.2)

    npm (我的版本 v6.1.0)


    npm 组件包 colors、qiniu

    node 的方法 fs、path、readline、console


    说明

    readline 用于从可读流(如 process.stdin)读取数据,每次读取一行文档说明

    colors 设置在控制台中颜色和样式风格 文档说明

    fs 文件系统操作 文档说明

    console 模块提供了一个简单的调试控制台,类似于 Web 浏览器提供的 JavaScript 控制台。 文档说明

    path 模块提供了一些工具函数,用于处理文件与目录的路径 文档说明

    qiniu 适用于Node.js的Qiniu云SDK 文档说明


    除了qiniu 其他包已默认安装
    执行命令
    npm install qiniu
    

    大体思路

    上传
    利用node的文件处理机制, 拿到指定目录下的所有文件,通过qiniuSDk一键上传到七牛云存储
    
    批量更新
    利用 qiniuSDK 获取远程指定筒和某前缀下的文件列表 批量删除后 再将本地文件全部上传
    

    具体实现

    创建 qiniu.js 文件

    1.引入所需依赖

    const readline  = require('readline')
    const colors = require( "colors");
    const FS = require('fs')
    const Join = require('path').join // 路径片段连接到一起,并规范化生成的路径
    const QiNiu = require('qiniu')
    

    2.初始化配置

    七牛秘钥

    const accessKey = '*******'; // 七牛秘钥
    const secretKey = '*******'; // 七牛秘钥
    const bucket = '***' // 七牛空间名(筒名)
    const prefix = '***' // 七牛目录名称(前缀)
    const limit = 10 // 分页请求 每页数量
    var uploadNore =  ['index.html'] // 忽略文件数组(可以为文件或文件夹)忽略文件数组(可以为文件或文件夹)
    
    // 鉴权对象
    const mac = new QiNiu.auth.digest.Mac(accessKey, secretKey);
    // 获取七牛配置
    const config = new QiNiu.conf.Config();
    // 是否使用https域名
    // config.useHttpsDomain = true;
    // 上传是否使用cdn加速
    // config.useCdnDomain = true;
    // 空间对应的机房 Zone_z0(华东)
    config.zone = QiNiu.zone.Zone_z0;
    // 资源管理相关的操作首先要构建BucketManager对象
    const bucketManager = new QiNiu.rs.BucketManager(mac, config);
    // 相关颜色配置 console颜色主题
    colors.setTheme({
      silly: 'rainbow',
      input: 'grey',
      verbose: 'cyan',
      prompt: 'grey',
      info: 'green',
      data: 'grey',
      help: 'cyan',
      warn: 'yellow',
      debug: 'blue',
      error: 'red'
    });
    // 
    

    3.定义相关方法

    3.1 获取远程七牛 指定空间名和前缀名的

    // 这里采用异步方法操作 获取远程列表的目的只是为了删除 但只能是获取到列表后 回调里再删除
    // 获取远程七牛 指定前缀 文件列表
    async function getQiniuList() {
      var options = {
        limit: limit,
        prefix: prefix,
      }
      var array = []
      var list = await getList()
      // marker 上一次列举返回的位置标记,作为本次列举的起点信息
      async function getList(mark=false) {
        if(mark){
          var options = {
            limit: options.limit,
            prefix: options.prefix,
            mark: mark
          }
        }
        return new Promise(function(resolve, reject){
          bucketManager.listPrefix(bucket, options, function(err, respBody, respInfo) {
            if (err) {
              console.log(err);
              throw err;
            }
            if (respInfo.statusCode == 200) {
              //如果这个nextMarker不为空,那么还有未列举完毕的文件列表,下次调用listPrefix的时候,指定options里面的marker为这个值
              var nextMarker = respBody.marker;
              var commonPrefixes = respBody.commonPrefixes;
              var items = respBody.items;
              items.forEach(function(item) {
                array.push(QiNiu.rs.deleteOp(bucket, item.key))
              });
              if(respBody.marker){
                getList(respBody.marker)
              } else{
                resolve(array)
              }
            } else {
              console.log(respInfo.statusCode);
              console.log(respBody);
            }
          });
        })
      }
      return list
    }
    

    3.2 删除远程 七牛列表数据

    // 批量删除远程七牛 指定列表 所有文件
    async function delAll(){
      async function delQiniuAll() {
        return new Promise(function(resolve, reject){
          // 获取七牛远程列表数据
          getQiniuList().then(res => {
            if (res.length!==0){
              console.log('远程列表为空'.debug);
              del(res, resolve)
            } else {
              resolve()
            }
          })
        })
      }
      await delQiniuAll()
    }
    function del(deleteOperations, resolve) {
      bucketManager.batch(deleteOperations, function(err, respBody, respInfo) {
        if (err) {
          console.log(err);
          //throw err;
        } else {
          // 200 is success, 298 is part success
          if (parseInt(respInfo.statusCode / 100) == 2) {
            respBody.forEach(function(item, index) {
              if (item.code == 200) {
                resolve(index)
                console.log('删除成功'+'第'+(parseInt(index)+1)+'个文件'.info)
              } else {
                console.log('删除失败'.error);
                console.log(item.code + "\t" + item.data.error.error);
                resolve(index)
              }
            });
          } else {
            console.log(respInfo.deleteusCode);
            console.log(respBody);
          }
        }
      });
    }
    

    3.3 上传本地 文件到七牛

    // 上传所有文件到骑牛
    function upAllToQiniu(){
      console.log('开时删除七牛远程资源列表'.debug);
      // 先删除所有 再上传
      delAll().then(res => {
        console.log('开时上传资源到七牛'.debug);
        var files = FS.readdirSync('dist/'); // 文件目录
        var localFile = findSync('dist/')
        // key 为远程 七牛目录文件名
        // localFile[key] 为本地完成路径+文件名称
        for(var key in localFile){
          upOneToQiniu(localFile[key], key)
        }
      })
    }
    
    // 上传单文件到骑牛 localFile为本地完成路径+文件名称 key为远程 七牛目录文件名
    function upOneToQiniu(localFile, key) {
      var mac = new QiNiu.auth.digest.Mac(accessKey, secretKey);
      var options = {
        scope: bucket,
      };
      var putPolicy = new QiNiu.rs.PutPolicy(options);
      var uploadToken = putPolicy.uploadToken(mac);
      var formUploader = new QiNiu.form_up.FormUploader(config)
      var putExtra = new QiNiu.form_up.PutExtra()
      // 文件上传
      formUploader.putFile(uploadToken, key, localFile, putExtra, function(respErr,
        respBody, respInfo) {
        if (respErr) {
          throw respErr
        }
        if (respInfo.statusCode == 200) {
          console.log(localFile.info+'=>'+respBody.key.info + '上传成功')
        } else {
          console.log('上传失败' + respInfo.statusCode.error);
          console.log('上传失败' + respBody.error)
        }
      })
    }
    // 拿到文件 目录路径 startPath 根目录名称
    function findSync(startPath) {
      let targetObj={};
      function finder(path) {
        // 获取当前目录下的 文件或文件夹
        let files=FS.readdirSync(path);
        // 循环获 当前目录下的所有文件
        files.forEach((val,index) => {
          let fPath=Join(path,val);
          let stats=FS.statSync(fPath);
          if(stats.isDirectory()) {
            finder(fPath);
          }
          if(stats.isFile() && isNore(fPath)) {
            targetObj[fPath.replace(startPath, prefix)] = fPath;
          }
        });
      }
      finder(startPath);
      return targetObj;
    }
    /**
     * 判断当前路径是否在忽略文件数组中
     * @param {String} path 路径
     */
    function isNore(path) {
      for( var item of uploadNore) { // 遍历忽略数组
        if (path.indexOf(item) !== -1) {
          return false
        }
      }
      return true
    }
    

    4.流程控制

    // process 对象是一个全局变量,它提供当前 Node.js 进程的有关信息,以及控制当前 Node.js 进程 因为是全局变量,所以无需使用 require()。
    var rl = readline.createInterface({
      input: process.stdin, // 要监听的可读流
      output: process.stdout, // 要写入逐行读取数据的可写流
      prompt: ('是否进行远程部署> (Y/N)').warn
    });
    rl.prompt();
    // 每当 input 流接收到接收行结束符(\n、\r 或 \r\n)时触发 'line' 事件。 通常发生在用户按下 <Enter> 键或 <Return> 键。监听器函数被调用时会带上一个包含接收的那一行输入的字符串。
    rl.on('line', (line) => {
      switch (line.trim()) {
        case 'y':
        case 'Y':
          console.log('开始执行远程部署'.help);
          // 上传
          upAllToQiniu()
          rl.close();
          break;
        case 'n':
        case 'N':
          console.log('您取消了远程部署'.help);
          rl.close();
          break;
        default:
          console.log(`你输入的:'${line.trim()}'为无效命令,请重新输入`.warn);
          rl.prompt();
          break;
      }
    })
    

    最后 在终端里 执行 node build/qiniu.js
    或者 在 package.json scripts项 里 加入

    "qiniu": "node build/qiniu.js",
    

    然后执行 npm run qiniu 也可以

    本文为作者原创,允许转载,转载后请以链接形式说明文章出处. 如转载但不标明来源,后果自负。

    王浩的博客

    相关文章

      网友评论

        本文标题:利用node 一键部署静态资源到 七牛

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