• 它需要知道服务端最新的版本信息;
    • 它需要知道是否有最新版本,也就是版本比较问题;
    • 在有更新版本的时候,需要从哪下载更新包;
    • 下载的更新包是否是遭到篡改问题;
    • 它需要能够执行更新程序,在更新完毕后自动启动程序以便用户继续使用;
      第一个问题可以配置一个最新版本的文件,存放在服务端,这样客户端在每次启动的时候就需要读取版本文件的URL地址,获取URL地址的版本信息SVersion.json;

    第二个问题:在比较版本的时候,需要在SVersion.json中读取到框架版本号和应用版本号,程序在启动的时候进行比较版本号,发现有更新;

    第三个问题:如果发现有更新的程序,需要从SVersion.json中获取最新的框架安装包或者最新的应用安装包下载地址,然后下载更新包;

    第四个问题:对于下载的安装包,需要用MD5来计算哈希值,与SVersion.json中的哈希值进行比对,这样就验证了有效性。

    第五个问题:运行下载的安装包,程序本身退出,在更新包安装完毕能够启动程序。

    主要流程如下所示:

    在服务端某个URL路径存放的更新配置文件(SVersion.json),需要记录框架版本号和应用版本号;同时最新框架更新包和应用更新包的下载地址以及他们的MD5哈希值,下面有个示例:

    在服务端同时要存放最新框架更新包和应用更新包,同时对安装包进行计算哈希值,下面的代码就是计算MD5哈希值的示例:

    1. var fs = require('fs')
    2. function md5File (filename, cb) {
    3. if (typeof cb !== 'function') throw new TypeError('Argument cb must be a function')
    4. var output = crypto.createHash('md5')
    5. var input = fs.createReadStream(filename)
    6. input.on('error', function (err) {
    7. cb(err)
    8. })
    9. output.once('readable', function () {
    10. })
    11. input.pipe(output)
    12. }
    13. //计算框架安装包的哈希值
    14. md5File('E:/electron_app/SetUp.exe',function (err, hash) {
    15. });
    16. //计算应用安装包的哈希值
    17. md5File('E:/electron_app/SetUp_App.exe',function (err, hash) {
    18. console.log('app exe hash result is '+hash);
    19. });

    为了实现自动更新,我们写了个组件,该组件能够根据配置文件的URL地址参数和框架版本号等参数,自动比较版本,进行下载安装包并比对哈希值,运行安装包等功能。但是该组件运行在程序的启动过程中,需要在主进程中调用。

    安装组件

    1. npm install erayt-updater --save

    方法

    • setFeedURL方法
      该方法主要是传入参数:SVersion.json的URL地址;框架版本号;应用版本号和更新包下载的本地存储路径。
    1. var auto = require('erayt-updater');
    2. auto.setFeedURL({
    3. updateURL:AUTO_UPDATE_URL,//SVersion.json的URL
    4. frameVer:process.versions.electron,//electron 版本
    5. appVer:app.getVersion(),//app 版本
    6. downloadPath:app.getPath('downloads')//更新包下载存储的路径
    7. });
    • checkForUpdates方法
      该方法主要功能是进行版本比对;下载安装包和安装包的哈希值验证的功能。该方法使用的前提是利用setFeedURL方法设置好了参数。
    • quitAndInstall方法
      该方法是创建子进程执行下载文件夹里面的更新包程序功能,这样主框架调用退出程序就可以安装更新包了。
    1. console.log('本应用程序退出,更新程序即将安装');
    2. auto.quitAndInstall(exePath);
    3. app.quit();

    事件

    当更新发生错误的时候触发,参数err是错误信息

    1. auto.on('update-error',(err)=>{
    2. console.error('自动更新期间出现错误;%s',err);
    3. });
    • 事件:'checking-for-update'

    当开始检查更新的时候触发,无参数。

    1. auto.on('checking-for-update',()=>{
    2. console.log('开始进行自动更新');
    3. });
    • 事件:'update-available'
      当发现一个可用更新的时候触发,更新包下载会自动开始,参数:

    isframe:是主框架需要更新还是应用程序包需要更新;

    version:最新更新的版本号;

    downloadurl:最新更新包的下载地址;

    originMd5:更新包的MD5哈希值

    • 事件:‘update-user-cancel’

    用户取消了本次更新触发的事件

    1. auto.on('update-user-cancel',()=> {
    2. console.log('用户取消更新');
    3. //启动显示主窗口
    4. });
    • 事件:'update-not-available'
    1. auto.on('update-not-available',()=> {
    2. console.log('没有可用的应用更新');
    3. //启动显示主窗口
    4. });
    • 事件:'update-downloaded'

    在更新下载完成的时候触发,参数为更新包下载到本地的绝对路径

    1. auto.on('update-downloaded',(localpath)=>{
    2. console.info('更新程序已经下载完成,下载路径为%s',localpath);
    3. setTimeout(()=> {
    4. console.log('本应用程序退出,更新程序即将安装');
    5. auto.quitAndInstall(localpath);//调用该exe执行
    6. return app.quit();//本程序退出
    7. },1000);
    8. });

    组件erayt-updater是在electron的主进程里面使用的,主进程也就是运行package.json里的main脚本的进程,并且electron官网也建议我们在app的事件中启动自动更新,所以我们在主进程的app的will-finish-launching事件回调函数中调用组件的checkForUpdates方法来开始更新。同时我们需要给用户显示是否有更新、更新的版本信息或者更新出错信息,所以需要开发者制作个窗口来显示。

    更新信息界面

     自动更新  - 图1

    更新进度界面:在有更新的时候,在启动界面中弹出BootStrap模态框来显示下载进度和更新的版本信息。

    更新错误界面:在出错页面中,显示更新出错信息。

     自动更新  - 图2

    自动更新示例

    首先安装erayt-updater组件,然后制作两个更新的html页面,在主进程的main.js里面的app事件中启动更新,监听组件事件,然后显示在更新界面中,如果没有更新、更新出错与用户取消更新则显示主界面,存在更新并下载完更新包调用更新包退出程序。