- 它需要知道服务端最新的版本信息;
- 它需要知道是否有最新版本,也就是版本比较问题;
- 在有更新版本的时候,需要从哪下载更新包;
- 下载的更新包是否是遭到篡改问题;
- 它需要能够执行更新程序,在更新完毕后自动启动程序以便用户继续使用;
第一个问题可以配置一个最新版本的文件,存放在服务端,这样客户端在每次启动的时候就需要读取版本文件的URL地址,获取URL地址的版本信息SVersion.json;
第二个问题:在比较版本的时候,需要在SVersion.json中读取到框架版本号和应用版本号,程序在启动的时候进行比较版本号,发现有更新;
第三个问题:如果发现有更新的程序,需要从SVersion.json中获取最新的框架安装包或者最新的应用安装包下载地址,然后下载更新包;
第四个问题:对于下载的安装包,需要用MD5来计算哈希值,与SVersion.json中的哈希值进行比对,这样就验证了有效性。
第五个问题:运行下载的安装包,程序本身退出,在更新包安装完毕能够启动程序。
主要流程如下所示:
在服务端某个URL路径存放的更新配置文件(SVersion.json),需要记录框架版本号和应用版本号;同时最新框架更新包和应用更新包的下载地址以及他们的MD5哈希值,下面有个示例:
在服务端同时要存放最新框架更新包和应用更新包,同时对安装包进行计算哈希值,下面的代码就是计算MD5哈希值的示例:
var fs = require('fs')
function md5File (filename, cb) {
if (typeof cb !== 'function') throw new TypeError('Argument cb must be a function')
var output = crypto.createHash('md5')
var input = fs.createReadStream(filename)
input.on('error', function (err) {
cb(err)
})
output.once('readable', function () {
})
input.pipe(output)
}
//计算框架安装包的哈希值
md5File('E:/electron_app/SetUp.exe',function (err, hash) {
});
//计算应用安装包的哈希值
md5File('E:/electron_app/SetUp_App.exe',function (err, hash) {
console.log('app exe hash result is '+hash);
});
为了实现自动更新,我们写了个组件,该组件能够根据配置文件的URL地址参数和框架版本号等参数,自动比较版本,进行下载安装包并比对哈希值,运行安装包等功能。但是该组件运行在程序的启动过程中,需要在主进程中调用。
安装组件
npm install erayt-updater --save
方法
- setFeedURL方法
该方法主要是传入参数:SVersion.json的URL地址;框架版本号;应用版本号和更新包下载的本地存储路径。
var auto = require('erayt-updater');
auto.setFeedURL({
updateURL:AUTO_UPDATE_URL,//SVersion.json的URL
frameVer:process.versions.electron,//electron 版本
appVer:app.getVersion(),//app 版本
downloadPath:app.getPath('downloads')//更新包下载存储的路径
});
- checkForUpdates方法
该方法主要功能是进行版本比对;下载安装包和安装包的哈希值验证的功能。该方法使用的前提是利用setFeedURL方法设置好了参数。
- quitAndInstall方法
该方法是创建子进程执行下载文件夹里面的更新包程序功能,这样主框架调用退出程序就可以安装更新包了。
console.log('本应用程序退出,更新程序即将安装');
auto.quitAndInstall(exePath);
app.quit();
事件
当更新发生错误的时候触发,参数err是错误信息
auto.on('update-error',(err)=>{
console.error('自动更新期间出现错误;%s',err);
});
- 事件:'checking-for-update'
当开始检查更新的时候触发,无参数。
auto.on('checking-for-update',()=>{
console.log('开始进行自动更新');
});
- 事件:'update-available'
当发现一个可用更新的时候触发,更新包下载会自动开始,参数:
isframe:是主框架需要更新还是应用程序包需要更新;
version:最新更新的版本号;
downloadurl:最新更新包的下载地址;
originMd5:更新包的MD5哈希值
- 事件:‘update-user-cancel’
用户取消了本次更新触发的事件
auto.on('update-user-cancel',()=> {
console.log('用户取消更新');
//启动显示主窗口
});
- 事件:'update-not-available'
auto.on('update-not-available',()=> {
console.log('没有可用的应用更新');
//启动显示主窗口
});
- 事件:'update-downloaded'
在更新下载完成的时候触发,参数为更新包下载到本地的绝对路径
auto.on('update-downloaded',(localpath)=>{
console.info('更新程序已经下载完成,下载路径为%s',localpath);
setTimeout(()=> {
console.log('本应用程序退出,更新程序即将安装');
auto.quitAndInstall(localpath);//调用该exe执行
return app.quit();//本程序退出
},1000);
});
组件erayt-updater是在electron的主进程里面使用的,主进程也就是运行package.json里的main脚本的进程,并且electron官网也建议我们在app的事件中启动自动更新,所以我们在主进程的app的will-finish-launching事件回调函数中调用组件的checkForUpdates方法来开始更新。同时我们需要给用户显示是否有更新、更新的版本信息或者更新出错信息,所以需要开发者制作个窗口来显示。
更新信息界面
更新进度界面:在有更新的时候,在启动界面中弹出BootStrap模态框来显示下载进度和更新的版本信息。
更新错误界面:在出错页面中,显示更新出错信息。
自动更新示例
首先安装erayt-updater组件,然后制作两个更新的html页面,在主进程的main.js里面的app事件中启动更新,监听组件事件,然后显示在更新界面中,如果没有更新、更新出错与用户取消更新则显示主界面,存在更新并下载完更新包调用更新包退出程序。