• electron打包后主进程下载文件崩溃


    electron+vue3写了一个小项目,实现了一个文件下载功能

    存在的问题

    	打包后,应用下载文件崩溃
    
    • 1

    代码

    // 渲染进程
     window.electron.ipcRenderer.invoke(
          'save-file', {
            'path': r.filePath,
            'fileurl': previewUrl,
          }
        ).then(response => {
          console.log('response --------------');
          console.log(response);
        })
    
    
    // 主进程
    ipcMain.handle('save-file', (event, args) => {
      // process.crash()
      try {
        // 下载保存文件
        console.log('axios args.fileurl ------------');
        console.log(args.fileurl);
        return downloadFile(args.fileurl, args.path)
      } catch (error) {
        console.log('error ---------------------------')
        console.log(error)
        return 'save-file 出错了: \n' + error.toString()
      }
    });
    
    
    // 工具文件
    import axios from 'axios'
    import fs from 'fs/promises'
    
    export function downloadFile(downloadUrl, downloadPath) {
      try {
        return axios.get(downloadUrl, {
          method: 'GET',
          headers: {
              "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36",
              "Referer": downloadUrl,
          },
          responseType: 'arraybuffer'
        }).then(res => {
          console.log('下载成功')
          return fs.writeFile(downloadPath, res.data, "binary").then(r => {
            console.log('保存成功')
            return fs.stat(downloadPath)
          });
        }).catch(e => {
          console.log('e ------------------')
          console.log(e)
          return e
        });
      } catch (error) {
        console.log('error ---------------------------')
        console.log(error)
        return 'downloadFile 出错了: \n' + error.toString()
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    解决思路

    首先,要复现,我测试了自己的笔记本电脑,双系统都没问题,没办法复现这个bug,但是测试那边两台电脑都能复现,测试是在外地!我只好又找了一台闲置电脑,还好复现出来了,否则只能回家试试自己的电脑了

    第二,找到问题所在,打包后 console.log 就看不到了,我想办法记录日志,看了官方的crashReporter,还有不少人推荐,我正好全栈,就搞了个接口接收日志,但是没有任何报错。后来试了electron-log,记录在用户本地,真香,简单好用,以后有需要直接搞个接口上传log文件就好了!还是没报错!但是我锁定了有问题的那一行代码,就是 axios.get(downloadUrl, { 这里崩溃的!

    第三,想办法换掉axios!试了第三方electron下载库,electron-download、electron-dl、都很难用,文档少,搜索结果更少,自己摸索半天也没跑起来,继续换electron-download-manage,但是这个东西调用很麻烦!换request下载,和axios比较像,还是不行!我觉得我的方向可能错了,灵机一动,把axios下载放在渲染进程里面,下载好的数据传递给主进程!好了!

    代码

    // 渲染进程
        axios.get(previewUrl, {
          method: 'GET',
          responseType: 'arraybuffer'
        }).then(res => {
          console.log('下载成功')
          console.log('下载成功')
          console.log('下载成功')
          console.log(typeof res.data)
          window.electron.ipcRenderer.invoke(
            'save-file', {
              'data': res.data,
              'path': r.filePath,
            }
          ).then(response => {
            console.log('response --------------');
            console.log(response);
          })
    
    
    // 主进程
    
    ipcMain.handle('save-file', (event, args) => {
      try {
        log.info('event, args ------------');
        log.info(event, args);
        // 保存文件
        return saveFile(args.data, args.path)
      } catch (error) {
        log.info('error ---------------------------')
        log.info(error)
        return 'save-file 出错了: \n' + error.toString()
      }
    });
    
    // 工具js
    import fs from 'fs/promises'
    import log from 'electron-log'
    import { Buffer } from 'buffer'
    
    export function saveFile(data, downloadPath) {
      log.info('saveFile ----------------------- 0')
      try {
        log.info('saveFile ----------------------- 1')
        return fs.writeFile(downloadPath, Buffer.from(data), "binary").then(r => {
          log.info('保存成功')
          return fs.stat(downloadPath)
        });
      } catch (error) {
        log.info('saveFile ----------------------- 3')
        log.info('error ---------------------------')
        log.info(error)
        throw new Error('saveFile出错了:' + error.toString()) // 将错误包装成新的Error对象并抛出,让调用者知道发生了错误
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    中间还发生了一个小插曲

    Error occurred in handler for 'save-file': 
    TypeError [ERR_INVALID_ARG_TYPE]: 
    The "data" argument must be of type string or an instance of 
    Buffer, TypedArray, or DataView. Received an instance of ArrayBuffer
    
    • 1
    • 2
    • 3
    • 4

    所以才有了Buffer.from(data)
    感谢文心一言,感谢我自己!

  • 相关阅读:
    【LCR 170. 交易逆序对的总数】
    第三章:最新版零基础学习 PYTHON 教程(第六节 - Python 运算符—Python 中的赋值运算符)
    RabbitMQ-java使用消息队列
    提升代码可读性,减少if-else的几个小技巧
    BUUCTF msic 专题(115)[安洵杯 2019]easy misc
    Codeforces Round 901 (Div. 2)
    Flask 自建扩展
    Centos7处理openssh漏洞后造成GNOME桌面启动异常
    企业数据泄漏事件频发,如何防止企业数据泄漏?
    基于Unity设计的井字棋小游戏
  • 原文地址:https://blog.csdn.net/weixin_39990025/article/details/133754760