electron -autoUpdater 更新及热更新

electron 更新有几种方式,可以看下官网的一些介绍 。这里我们开发的是一个私有的 Electron 应用程序,下面有两种更新方式,一是整个exe更新,第二个是局部热更新,只更新app.asar文件。这里我结合两种方法,先判断有没有exe更新,再判断是否需要热更新

exe更新,使用autoUpdater 实现。参考链接

局部热更新,使用electron-asar-hot-updater 实现,参考链接

1、安装支持包

npm install electron-updater --save
npm install electron-asar-hot-updater -s  

2、在main.js实现

import {autoUpdater} from "electron-updater"
const EAU = require('electron-asar-hot-updater');
const isDevelopment = process.env.NODE_ENV !== 'production'

function handleUpdate() {


  // 更新前,删除本地安装包 ↓
  let updaterCacheDirName = 'xxapp-updater'
  const updatePendingPath = path.join(autoUpdater.app.baseCachePath, updaterCacheDirName, 'pending')
  
  fs_extra.emptyDir(updatePendingPath)
   // 更新前,删除本地安装包 ↑
  log.info("updatePendingPath=" + updatePendingPath);
  const returnData = {
      error: {status: -1, msg: '检测更新查询异常'},
      checking: {status: 0, msg: '正在检查应用程序更新'},
      updateAva: {status: 1, msg: '检测到新版本,正在下载,请稍后'},
      updateNotAva: {status: -1, msg: '您现在使用的版本为最新版本,无需更新!'},
  };
  // 本地开发环境,改变app-update.yml地址
  if (process.env.NODE_ENV === 'development') {
    var dev_path = path.join(__dirname, 'win-unpacked/resources/app-update.yml');
    log.info("dev_path=" + dev_path);
    autoUpdater.updateConfigPath = dev_path;

    // mac的地址是'Contents/Resources/app-update.yml'
  }else {
    var dev_path = path.join(__dirname, '../app-update.yml');
    log.info("dev_path=" + dev_path);
    autoUpdater.updateConfigPath = dev_path;

  }
  //log.info("autoUpdater.updateConfigPath=" + autoUpdater.updateConfigPath);
  //和之前package.json配置的一样

  autoUpdater.setFeedURL('http://update.tuzhitong.com/download/update');
  //autoUpdater.setFeedURL({"headers": "get","url": "http://update.xxx.com/download/update"});
  //更新错误
  autoUpdater.on('error', function (error) {
      
      sendUpdateMessage(returnData.error)
  });

  //检查中
  autoUpdater.on('checking-for-update', function () {
      sendUpdateMessage(returnData.checking)
  });

  //发现新版本
  autoUpdater.on('update-available', function (info) {
      if(!isDevelopment){
        sendUpdateMessage(returnData.updateAva)
      }else{
        sendUpdateMessage(returnData.updateNotAva)
      }
      
  });

  //当前版本为最新版本
  autoUpdater.on('update-not-available', function (info) {
      setTimeout(function () {
          hotUpdate();//热更新检查
          sendUpdateMessage(returnData.updateNotAva)
      }, 1000);
  });

  // 更新下载进度事件
  autoUpdater.on('download-progress', function (progressObj) {
    win.webContents.send('updateAppProgress', progressObj)
    
  });


  autoUpdater.on('update-downloaded', function (event, releaseNotes, releaseName, releaseDate, updateUrl, quitAndUpdate) {

      // win.webContents.send('isUpdateNow',"isUpdateNow")
  });
  

  //执行自动更新检查
  //autoUpdater.checkForUpdates();
}



// 通过main进程发送事件给renderer进程,提示更新信息
function sendUpdateMessage(text) {
  //通知BrowserWindow页面显示进度条
  //win.webContents.send('updateAppMessage', text)
}
ipcMain.on('isUpdateNow', (e, arg) => {
  //some code here to handle event
  autoUpdater.quitAndInstall(true,true);

});

ipcMain.on("checkForUpdate", (event, data) => {
  //log.info('执行自动更新检查!!!');
  
  autoUpdater.checkForUpdates();

});

ipcMain.on('downloadUpdate', () => {
  // 下载
  autoUpdater.downloadUpdate()
})

handleUpdate();

function hotUpdate(){
  EAU.init({
    'api':'http://127.0.0.1:3176/api/apitest/postElectronUpdate', // The API EAU will talk to
    'server': false // Where to check. true: server side, false: client side, default: true.
  });

  EAU.check(function (error, last, body) {
    if (error) {
      if (error === 'no_update_available') { return false; }
      //dialog.showErrorBox('info', error)
      return false
    }

    win.webContents.send('beginUpdate')
    
    EAU.progress(function (state) {
      win.webContents.send('updateAppProgress', {percent:state.percent * 100} )
      // The state is an object that looks like this:
      // {
      //     percent: 0.5,               
      //     speed: 554732,              
      //     size: {
      //         total: 90044871,        
      //         transferred: 27610959   
      //     },
      //     time: {
      //         elapsed: 36.235,        
      //         remaining: 81.403       
      //     }
      // }
      if(state.percent >=1){
        
        //dialog.showMessageBox('info', 'App updated successfully! Restart it please.')
      }
    })

    EAU.download(function (error) {
      if (error) {
       // dialog.showErrorBox('info', error)
        return false
      }
      //通知页面显示进度条
     // win.webContents.send('updateAppProgress',{percent: 100} )
      setTimeout(() => {
        if (process.platform === 'darwin') {
          app.relaunch()
          app.quit()
        } else {
          app.quit()
        }
      }, 2000);

    })

  })
}


//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<处理更新操作 end

3、页面相关监听

<template>
    <el-dialog
                :title="UpdateInfo.title"
                :visible.sync="UpdateInfo.show"
                :show-close="false"
                :close-on-press-escape="false"
                :close-on-click-modal="false"
                center
                width="50%"
                top="45vh">
            <div class="conten">
                <el-progress :percentage="UpdateInfo.percentage" :color="UpdateInfo.colors" :status="UpdateInfo.progressStaus"></el-progress>
            </div>
    </el-dialog>
</template>

<script>
export default {
    data() {
        return {
            UpdateInfo:{show:false,percentage: 0,title:"下载进度",
                progressStaus :null,colors: [ { color: "#f56c6c", percentage: 20 }, { color: "#e6a23c", percentage: 40 },
                { color: "#6f7ad3", percentage: 60 }, { color: "#1989fa", percentage: 80 }, { color: "#5cb87a", percentage: 100 }
            ]},
        }
    },
    created: function () {
    },
    mounted: function () {
        this.checkForUpdate();

         /**
     * 主进程返回的检测状态
     */
     this.$ipcRenderer.on('updateAppMessage', (event, data) => {
      console.log("updateAppMessage" + data);
        switch (data.status) {
            case -1:
              console.log("updateAppMessage-error:" + data.msg);
                //this.$Message.error(data.msg);
                break;
            case 0:
                console.log("updateAppMessage-loading:" + data.msg);
                //this.$Message.loading(data.msg);
                break;
            case 1:
                _this.updateApp();
              
                break;
        }
    });

    },
    methods: {
        downloadUpdate () {
          var _this = this;
      var _isHotUpdate = false;
      this.$ipcRenderer.on('beginUpdate', () => {
 
          _isHotUpdate = true;
          _this.UpdateInfo.show = true;     
      });

      //更新进度
      this.$ipcRenderer.on('updateAppProgress', (event, data) => {
     
          _this.UpdateInfo.percentage =  data.percent.toFixed(0);//(data.percent).toFixed(2);
          console.log("data.percent =" + data.percent);
          if (data.percent >= 100) {
            console.log("isUpdateNow =");
            
            _this.UpdateInfo.title = "下载完成,即将自动重启应用";
            if(_isHotUpdate){              
              //_this.UpdateInfo.show = false;   
              
            }else{
              setTimeout(() => {   
                  _this.$ipcRenderer.send('isUpdateNow')
              }, 1000);
            }            
  
          }
      });
      
    },
    updateApp () {
      var _this = this;
      _this.$confirm('版本有更新,是否立即更新!').then(()=> {
          
          _this.UpdateInfo.show = true;
    
      }).catch(() => {
          
      })
    },
    checkForUpdate () {
        this.$ipcRenderer.send('checkForUpdate', 'a')
        this.downloadUpdate();
    },
  }

}

</script>

4、autoUpdater实现exe更新的时候需要再服务器上部署个人站点,需要以下几个文件

---latest.yml  (高版本bulider的时候生成)

---xxx_1.0.0.exe.blockmap(当前版本bulider生成)

---xxx_1.3.0.exe(高版本bulider生成)

---xxx_1.3.0.exe.blockmap(高版本bulider生成)

主要如果是放在iis上,需要添加mime (.yml  application/octet-stream )

5、electron-asar-hot-update 进行局部更新的时候需要访问一个api获取是否需要更新,如

        [HttpPost]
        public dynamic postElectronUpdate()
        {

            return new
            {
                name = "xxx",
                version = "1.4.0",
                asar = "http://127.0.0.1:2046/download/update/update.zip",
                info = "test"
            };
        }

此处的update.zip是打包路径下 win-unpacked\resources\app.asar 这个文件重命名为update.asar文件,然后压缩为zip文件

 

常见错误问题

1、验证更新时请不要在开发状态验证,不要在开发状态验证,不要在开发状态验证,会有一系列的问题,如MD5不匹配等

2、autoUpdater的服务端文件不要少,不然会报缺失文件

3、electron-asar-hot-update 进行局部更新的时候如果提示 “update.asar中不存在electron-asar-hot-update /update.exe” ,说明asar打包的时候没有把electron-asar-hot-update 这个node_modules打包进去。这个时候需要再配置里打包进去

pluginOptions: {
        electronBuilder: {
                externals:['electron-asar-hot-updater',....],
                ...
                            }
                }

 

 

 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值