UDN-企业互联网技术人气社区

板块导航

浏览  : 2106
回复  : 4

[Nodejs] nw.js桌面程序自动更新(node.js表白记)

[复制链接]
小辫儿的头像 楼主
发表于 2017-2-7 10:50:49 | 显示全部楼层 |阅读模式
  Hello Google 

  Node.js 一个基于Google V8 的JavaScript引擎。

  初次涉足Node.js实现的nw.js桌面程序的自动更新模块吧。

  下面说的这个模块是基于angular.js的,如此粗鄙的几行代码,还望各位同仁瞄眼之后便使劲的喷!

  一、机制分析

  此机制的优劣性暂且不议,这仅是目前我唯一能想到的!

  已经说了太多无聊的话,这个机制我就画个简单的草图来呈现吧。
1.png

  从图中不难看出,我所谓的这个自动更新机制其实仅4步而已:

  1.确定本地版本号与远端版本号

  2.检测版本与平台

  3.判断版本差异性

  4.是否存在差异的进一步处理

  二、模块实现

  1.模块依赖
  1. fs = require('fs');
  2. path = require('path');
  3. request = require('request');
  4. child_process = require('child_process');  
复制代码

  以下为依赖模块的简要释义:

  fs: node.js 文件系统模块

  path: node.js 文件路径模块

  request: node.js http模块

  child_process: node.js 子进程模块

  2.版本对比(使用文件读写模块对本地版本号的写入与更新)
  1. compareVer: function(RequestUrl) {
  2.     var remoteURL  = RequestUrl;
  3.     var deferred = $q.defer();
  4.     fs.readFile(path.join(nwDir, 'version.txt'), function(err, data) {
  5.         if(err) {
  6.             fs.writeFile(path.join(nwDir, 'version.txt'), '0.0.1', function(err) {
  7.                 if(err) throw err;
  8.             });
  9.             alert("系统检测到重要文件丢失,请手动重启应用!");
  10.        process.exit(0);
  11.         }else {
  12.             version.localVer = data;
  13.             $http.get(remoteURL).success(function(items) {
  14.                 if(items.code == 200) {
  15.                     version.remoteVer = items.data.version;
  16.                     var isUpdate = version.localVer && version.remoteVer && version.localVer != version.remoteVer ? true : false;
  17.                     items.isUpdate = isUpdate;
  18.                     if(isUpdate) {
  19.                         fs.writeFile(path.join(nwDir, 'version.txt'), version.remoteVer, function(err) {
  20.                             if(err) throw err;
  21.                         });
  22.                     }
  23.                     deferred.resolve(items);
  24.                 }
  25.             }).error(function(data, status, headers, config) {
  26.                 alert("程序初始化失败,请检查网络连接!");
  27.             });
  28.         }
  29.         
  30.     });
  31.     return deferred.promise;
  32. },
复制代码

  3.执行升级(使用http模块对差异版进行下载并执行文件流写入操作)
  1. update: function(DownloadUrl, total) {
  2.     request(DownloadUrl, function (error, response) {
  3.         if(!error && response.statusCode == 200) {
  4.             angular.element('.title').html('升级完成');
  5.             angular.element('#progress > span').html('100');
  6.             $interval.cancel(timer);

  7.             var t = 3;
  8.             var interval = $interval(function() {
  9.                 angular.element('.title').html('自动重启');
  10.                 angular.element('#progress').html('<span style="font-size: 5em;">'+ t-- +'</span>');
  11.                 if(t < 0) {
  12.                     win.hide()
  13.                     child_process.exec(file, function(err, stdout, stderr) {
  14.                         process.exit(0);
  15.                     });
  16.                     $interval.cancel(interval);
  17.                 }
  18.             }, 1000)
  19.         }
  20.     }).pipe(fs.createWriteStream(file));

  21.     var timer = $interval(function() {
  22.         var loaded = fs.statSync(file).size;
  23.      var percentComplete = loaded / total;
  24.         var downloadProgress = (percentComplete * 100).toFixed(1);
  25.         angular.element('#progress > span').html(downloadProgress);
  26.     }, 100);
  27.     return;
  28. }
复制代码

  4.无差异性处理(隐藏主进程并创建子进程)
  1. normal: function() {
  2.     win.hide();
  3.     child_process.exec(file, function(err, stdout, stderr) {
  4.         process.exit(0);
  5.     });
  6. },
复制代码

  三、完整模块代码
  1. /*
  2.     nw.js桌面程序自动更新module for angular
  3.     Author: BGONLINE
  4.     2016-12-29
  5. */
  6. (function(angular, factory) {
  7.     if(typeof define === 'function' && define.amd) {
  8.         define('bgo-update', ['angular'], function(angular) {
  9.             return factory(angular);
  10.         });
  11.     }else {
  12.         return factory(angular);
  13.     }
  14. }(typeof angular === 'undefined' ? null : angular, function(angular) {

  15. var module = angular.module('bgoUpdate', []);

  16. 'use strict';

  17. module

  18.     .factory('bgoAutoUpdate', ['$http', '$q', '$interval', '$timeout', function($http, $q, $interval, $timeout) {
  19.         var version = {
  20.             localVer: '',
  21.             remoteVer: ''
  22.         }
  23.          
  24.         var fs = require('fs');
  25.         var path = require('path');
  26.         var request = require('request');
  27.         var child_process = require('child_process');
  28.         var nwPath = process.execPath;
  29.         var nwDir = path.dirname(nwPath);
  30.         var file = path.join(nwDir, 'current.exe');
  31.         return {
  32.             normal: function() {
  33.                 var str = '';
  34.                 var interval = $interval(function() {
  35.                     str += '.';
  36.                     angular.element('#progress > span').html(str);
  37.                     if(str.length > 3) {
  38.                         win.hide()
  39.                         child_process.exec(file, function(err, stdout, stderr) {
  40.                             process.exit(0);
  41.                             $interval.cancel(interval);
  42.                         });
  43.                     }
  44.                 }, 1000)
  45.             },
  46.             
  47.             compareVer: function(RequestUrl) {
  48.                 var remoteURL  = RequestUrl;
  49.                 var deferred = $q.defer();
  50.                 fs.readFile(path.join(nwDir, 'version.txt'), function(err, data) {
  51.                     if(err) {
  52.                         fs.writeFile(path.join(nwDir, 'version.txt'), '0.0.1', function(err) {
  53.                             if(err) throw err;
  54.                         });
  55.                         layer.alert("系统检测到重要文件丢失,请手动重启应用!", {closeBtn: 0, icon: 5, shade: 0}, function() {
  56.                             layer.closeAll();
  57.                             process.exit(0);
  58.                         });
  59.                     }else {
  60.                         version.localVer = data;
  61.                         $http.get(remoteURL).success(function(items) {
  62.                             if(items.code == 200) {
  63.                                 version.remoteVer = items.data.version;
  64.                                 var isUpdate = version.localVer && version.remoteVer && version.localVer != version.remoteVer ? true : false;
  65.                                 items.isUpdate = isUpdate;
  66.                                 if(isUpdate) {
  67.                                     fs.writeFile(path.join(nwDir, 'version.txt'), version.remoteVer, function(err) {
  68.                                         if(err) throw err;
  69.                                     });
  70.                                 }
  71.                                 deferred.resolve(items);
  72.                             }
  73.                         }).error(function(data, status, headers, config) {
  74.                             layer.msg("程序初始化失败,请检查网络连接!", function() {});
  75.                         });
  76.                     }
  77.                     
  78.                 });
  79.                 return deferred.promise;
  80.             },

  81.             update: function(DownloadUrl, total) {
  82.                 request(DownloadUrl, function (error, response) {
  83.                     if(!error && response.statusCode == 200) {
  84.                         angular.element('.title').html('升级完成');
  85.                         angular.element('#progress > span').html('100');
  86.                         $interval.cancel(timer);

  87.                         var t = 3;
  88.                         var interval = $interval(function() {
  89.                             angular.element('.title').html('自动重启');
  90.                             angular.element('#progress').html('<span style="font-size: 5em;">'+ t-- +'</span>');
  91.                             if(t < 0) {
  92.                                 win.hide()
  93.                                 angular.element('.title').html('学籍系统保护模块');
  94.                                 angular.element('#progress > span').html('请勿关闭!');
  95.                                 child_process.exec(file, function(err, stdout, stderr) {
  96.                                     process.exit(0);
  97.                                 });
  98.                                 $interval.cancel(interval);
  99.                             }
  100.                         }, 1000)
  101.                     }
  102.                 }).pipe(fs.createWriteStream(file));

  103.                 var timer = $interval(function() {
  104.                     var loaded = fs.statSync(file).size;
  105.                  var percentComplete = loaded / total;
  106.                     var downloadProgress = (percentComplete * 100).toFixed(1);
  107.                     angular.element('#progress > span').html(downloadProgress);
  108.                 }, 100);
  109.                 return;
  110.             }
  111.         }
  112.     }])

  113.     return module;
  114. }));
复制代码

  四、模块调用
  1. App.controller('UpdateController', ["$rootScope", "$scope", 'bgoAutoUpdate', function($rootScope, $scope, bgoAutoUpdate) {

  2.     bgoAutoUpdate.compareVer($rootScope.rootUrl + 'index/login/getVersion?platform=' + process.platform).then(function(res) { // 判断版本
  3.         $scope.isUpdate = res.isUpdate;
  4.         if($scope.isUpdate) {
  5.             bgoAutoUpdate.update(res.data.fileUrl, res.data.fileSize, res.data.version); // 执行更新
  6.         }else {
  7.             bgoAutoUpdate.normal();
  8.         }
  9.     });
  10.    
  11. }]);
复制代码

相关帖子

发表于 2017-2-7 10:51:27 来自手机 | 显示全部楼层
总觉得哪里有点问题啊
使用道具 举报

回复

发表于 2017-2-11 01:35:48 | 显示全部楼层
总觉得哪里有点问题啊
使用道具 举报

回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部