Electron手写自动升级模块

主进程负责设置下载目录,下载,获取下载进度,安装;
渲染进程负责检查更新,展示更新界面,调用下载,显示下载进度,调用安装;

主进程模块

封装download.js,实现下载、进度获取、安装

const { ipcMain, dialog, shell } = require('electron')
const path = require('path')

exports.initDownload = function (win) {
  let downloadObj = {
    downloadPath: '', // 要下载的链接或文件
    fileName: '', // 要保存的文件名,需要带文件后缀名
    savedPath: '' // 要保存的路径
  }

  //重置信息
  function resetDownloadObj() {
    downloadObj = {
      downloadPath: '',
      fileName: '',
      savedPath: ''
    }
  }

  // 监听渲染进程发出的download事件
  ipcMain.on('download', (evt, args) => {
    downloadObj.downloadPath = args.downloadPath
    downloadObj.fileName = args.fileName
    let ext = path.extname(downloadObj.fileName)
    let filters = [{ name: '全部文件', extensions: ['*'] }]
    if (ext && ext !== '.') {
      filters.unshift({
        name: '',
        extensions: [ext.match(/[a-zA-Z]+$/)[0]]
      })
    }

    // 弹出另存为弹框,用于获取保存路径
    dialog.showSaveDialog(win, {
      filters,
      defaultPath: downloadObj.fileName
    }).then((result) => {
      downloadObj.savedPath = result.filePath
      if (downloadObj.savedPath) {
        win.webContents.downloadURL(downloadObj.downloadPath) // 触发will-download事件
      }
    }).catch(() => {})
  })

  //捕获下载事件
  win.webContents.session.on('will-download', (event, item) => {
    //设置文件存放位置
    item.setSavePath(downloadObj.savedPath)
    item.on('updated', (event, state) => {
      if (state === 'interrupted') {
        console.log('Download is interrupted but can be resumed')
      } else if (state === 'progressing') {
        if (item.isPaused()) {
          console.log('Download is paused');
        } else {
          console.log(`Received bytes: ${item.getReceivedBytes()}`);
          win.webContents.send('downloadProgressing', {progress:item.getReceivedBytes(),totalSize:item.getTotalBytes()});
        }
      }
    })
    item.once('done', (event, state) => {
      if (state === 'completed') {
        console.log('Download successfully');
        win.webContents.send('downloadCompleted', {filePath: downloadObj.savedPath});
      } else {
        win.webContents.send('downloadFailed', {});
        console.log(`Download failed: ${state}`);
      }
      resetDownloadObj()
    })
  })

  // 监听渲染进程发出的setup事件
  ipcMain.on('setup', (evt, {filePath}) => {
    console.log('setup', filePath)
    shell.showItemInFolder(filePath)
    shell.openPath(filePath)
    setTimeout(() => {
      !!win && win.close()
    },2000)
  })  
}

入口文件引用

...
const { initDownload } = require('./download')
...
//主程序初始化之后
initDownload(win);

渲染进程核心逻辑

调用主进程下载方法,接收下载进度,调用主进程安装

  let initAppVersionInfo = storage.getSessionItem(StorageKeys.AppVersionInfo);
  const [appVersionInfo] = useState(initAppVersionInfo);
  const [downLoadStatus, setDownLoadStatus] = useState('ready');//ready, downloading, downloaded, failed
  const [downloadProgress, setDownloadProgress] = useState(0);
  const [downloadTotalSize, setDownloadTotalSize] = useState(0);
  const [filePath, setFilePath] = useState('');
  const appName = `Setup${appVersionInfo?.version}.exe`;
  
  //判断是否有新版本信息
  function getHaveAppVersionInfo(){
    return !!appVersionInfo && (appVersionInfo?.updateType>=0)
  }

  //下载文件
  function download(){
    try {           
      setDownloadProgress(0);
      setDownloadTotalSize(0);
      ipcRenderer.send('download', {
        downloadPath: appVersionInfo?.updateLink, // 下载链接
        fileName: appName // 下载文件名,需要包含后缀名
      })

      ipcRenderer.removeAllListeners('downloadProgressing');
      ipcRenderer.removeAllListeners('downloadCompleted');
      ipcRenderer.removeAllListeners('downloadFailed');

      ipcRenderer.on('downloadProgressing', (event, res) => {
        console.log('downloadProgressing: ',res.progress,res.totalSize);
        setDownLoadStatus('downloading');
        setDownloadProgress(res.progress);
        setDownloadTotalSize(res.totalSize);
      });

      ipcRenderer.on('downloadCompleted', (event, res) => {
        console.log('downloadCompleted: ',res);
        setDownLoadStatus('downloaded');
        setFilePath(res.filePath);
        message.success('下载成功');
      });

      ipcRenderer.on('downloadFailed', (event, res) => {
        console.log('downloadFailed: ',res);
        setDownLoadStatus('failed');
        message.error('下载失败,请重试!');
      });

    } catch (error) {
      
    }
  }

  //安装文件
  function setup(){
    try {

      ipcRenderer.send('setup', {filePath: filePath});
    } catch (error) {
      
    }
  }

  //字节转kb mb gb tb
  function bytesToSize(bytes) {
    const sizes = ['B', 'K', 'M', 'G', 'T'];
    if (bytes === 0) return '0 B';
    const i = Math.floor(Math.log(bytes) / Math.log(1024));
    return (bytes / Math.pow(1024, i)).toFixed(2) + ' ' + sizes[i];
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值