electron-vue项目保存文件到指定目录

公司需要搞electron项目,我在这方面又是没接触过,上网搜也是没找到完整的代码(也可能我找的关键词不够精确),最后只能自己摸石头过河。记录下遇到的问题和解决的方法

在 Electron-Vue 项目中,下载文件到指定目录,需要在 Electron 的主进程中处理下载逻辑,并使用 Node.js 的 fs 模块和 axios 或其他 HTTP 客户端库来下载和保存文件。

环境:

"axios": "^1.6.8",
"path-browserify": "^1.0.1",
"qrcode": "^1.5.3",
"vue": "^2.6.14",
"vue-router": "^3.5.1"

初始示例代码

1. 主进程 (main.js 或其他主进程文件,我主进程文件名background.js)

在主进程中,你需要监听来自渲染进程的 IPC 消息,处理文件下载到指定目录。

const { ipcMain } = require('electron');
const fs = require('fs');
const axios = require('axios');
const path = require('path');

// 假设这是你的指定目录
const specifiedDirectory = path.join(__dirname, 'downloads');

// 确保目录存在
if (!fs.existsSync(specifiedDirectory)) {
  fs.mkdirSync(specifiedDirectory, { recursive: true });
}

ipcMain.on('download-file', async (event, options) => {
  try {
    // options 应该包含 url 和文件名
    const { url, filename } = options;
    const filePath = path.join(specifiedDirectory, filename);

    // 使用 axios 下载文件
    const response = await axios({
      method: 'get',
      url: url,
      responseType: 'stream'
    });

    // 写入文件
    const writer = fs.createWriteStream(filePath);

    return new Promise((resolve, reject) => {
      response.data.pipe(writer);

      let error = null;
      writer.on('error', err => {
        error = err;
        writer.close();
        reject(err);
      });

      writer.on('close', () => {
        if (!error) {
          resolve(true);
          event.reply('download-file-reply', { success: true, filePath });
        } else {
          event.reply('download-file-reply', { success: false, error });
        }
      });
    });
  } catch (error) {
    console.error('下载文件时出错:', error);
    event.reply('download-file-reply', { success: false, error });
  }
});

2. 渲染进程 (Vue 组件)

在 Vue 组件中,你可以通过 Electron 的 IPC 机制发送消息到主进程,请求下载文件。

<template>
  <div>
    <button @click="downloadFile">下载文件到指定目录</button>
  </div>
</template>

<script>
const { ipcRenderer } = require('electron');

export default {
  methods: {
    async downloadFile() {
      // 指定文件 URL 和文件名
      const url = 'https://example.com/path/to/file';
      const filename = 'downloaded-file.ext';

      // 发送 IPC 消息到主进程
      ipcRenderer.send('download-file', { url, filename });

      // 监听主进程的回复
      ipcRenderer.on('download-file-reply', (event, args) => {
        if (args.success) {
          console.log('文件下载成功:', args.filePath);
          // 可以在这里处理文件下载成功的逻辑,比如显示通知等
        } else {
          console.error('文件下载失败:', args.error);
          // 可以在这里处理文件下载失败的逻辑
        }
      });
    },
  },
  // ... 其他代码 ...
};
</script>

遇到的问题

问题1:.store目录像一个缓存或临时目录。

error  in ./node_modules/.store/electron@13.6.9/node_modules/electron/index.js
Module not found: Error: Can't resolve 'fs' in 'D:\VSCodeProject\smart_screen\node_modules\.store\electron@13.6.9\node_modules\electron'

error  in ./node_modules/.store/electron@13.6.9/node_modules/electron/index.js
Module not found: Error: Can't resolve 'path' in 'D:\VSCodeProject\smart_screen\node_modules\.store\electron@13.6.9\node_modules\electron'
解决:

1、删除node_modules目录和package-lock.json(或yarn.lock)文件

2、运行npm cache clean --force清除npm缓存,不然直接npm install重新安装依赖还是一样问题

3、重新运行npm install来安装依赖项

问题2:Webpack默认配置不支持这些模块

If you want to include a polyfill, you need to:
        - add a fallback 'resolve.fallback: { "path": require.resolve("path-browserify") }'
        - install 'path-browserify'
If you don't want to include a polyfill, you can use an empty module like this:
        resolve.fallback: { "path": false }
对于path模块,使用path-browserify作为polyfill

安装polyfills

npm install path-browserify --save

或者,如果使用yarn:
yarn add path-browserify

 配置Webpack

在您的Webpack配置文件中(通常是webpack.config.js,vue项目在vue.config.js),您需要添加一个resolve.fallback条目来指定当Webpack无法解析path模块时应该使用哪个polyfill

// vue.config.js
module.exports = {
  configureWebpack: {
    resolve: {
      // 你的 Webpack resolve 配置项
    }
  },
  // 其他配置项...
};

后面还遇到一些其他奇奇怪怪的,记录这个的时候忘记了,就不去想了,下面直接贴代码

完整代码

vue.config.js

const { defineConfig } = require('@vue/cli-service');

module.exports = defineConfig({
  transpileDependencies: true,
  pluginOptions: {
    electronBuilder: {
      preload: 'src/preload.js',  // Specify the path to your preload script
      customFileProtocol: "./",  // 静态资源路径矫正(不配置打包后,路径不正确加载失败)
    }
  },
  configureWebpack: {
    resolve: {
      // ... 您的其他resolve配置 ...
      fallback: {
        "path": require.resolve("path-browserify")
      },
    }
  }
});
preload.js

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electron', {
  downloadFile: async (options) => {
    try {
      const { url, filename } = options;
      return await ipcRenderer.invoke('download-file', { url, filename });
    } catch (error) {
      console.error('下载文件时出错:', error);
      return { success: false, error: error.message };
    }
  }
});
background.js

const { app, protocol, BrowserWindow, ipcMain  } = require('electron')
const { createProtocol } = require('vue-cli-plugin-electron-builder/lib')

const fs = require('fs');
import axios from 'axios';
const path = require('path');
// 指定目录
const specifiedDirectory = path.join(__dirname, 'src/assets/img');
// 确保目录存在
if (!fs.existsSync(specifiedDirectory)) {
  fs.mkdirSync(specifiedDirectory, { recursive: true });
}

async function createWindow() {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 1280,
    height: 800,
    webPreferences: {
      nodeIntegration: false, //process.env.ELECTRON_NODE_INTEGRATION, // 设置为 false,禁用 Node.js 集成
      contextIsolation: true,//!process.env.ELECTRON_NODE_INTEGRATION, // 启用上下文隔离
      webSecurity: false,//允许跨域
      preload: path.join(__dirname, 'preload.js')
    }
  })
}

app.on('ready', async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      //await installExtension(VUEJS_DEVTOOLS)
    } catch (e) {
      console.error('Vue Devtools failed to install:', e.toString())
    }
  }
  createWindow()
  
  ipcMain.handle('download-file', async (event, options) => {
    try {
      // options 应该包含 url 和文件名
      const { url, filename } = options;
      const filePath = path.join(specifiedDirectory, filename);
  
      // 使用 axios 下载文件
      const response = await axios.get(url, { responseType: 'stream' });
      const writer = fs.createWriteStream(filePath);
  
      return new Promise((resolve, reject) => {
        response.data.pipe(writer);
  
        let error = null;
        writer.on('error', err => {
          error = err;
          writer.close();
          reject(err);
        });
  
        writer.on('close', () => {
          if (!error) {
            resolve({ success: true, filePath }); // 返回成功信息
          } else {
            reject({ success: false, error: error.message }); // 返回错误信息
          }
        });
      });
    } catch (error) {
      console.error('下载文件时出错:', error);
      event.reply('download-file-reply', { success: false, error: error.message });
    }
  });
})

上面background.js这里搞错了,应该是return Promise.reject才对

try{
    
} catch (error) {
    console.error('下载文件时出错:', error);
    return Promise.reject('download-file-reply', { success: false, error: error.message         
});
调用的js文件
this.download('http://www.***.***.com/img/logo/202312/1221_165322_HQz6.png', 'file.png');

    /**
     * 文件下载指定目录(background.js: 'src/assets/img')
     * @param {*} fileUrl 待下载文件url
     * @param {*} fileName 文件保存名
     */
    async download(fileUrl, fileName) {
      const options = {
        url: fileUrl,
        filename: fileName
      };
      const result = await window.electron.downloadFile(options);
      if (result.success) {
        console.log('文件下载成功:', result.filePath);
      } else {
        console.error('文件下载失败:', result.error);
      }
    },

 

后文:electron小白记录,文章有什么用语还是其他不对的地方欢迎斧正。大家一起进步,冲冲冲! 

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: electron-vue 是一个使用 Vue.js 开发跨平台桌面应用的框架,可以使用 electron-builder 工具将其打包成 exe 文件。 以下是将 electron-vue 项目打包成 exe 的基本步骤: 1. 安装 electron-builder 在 electron-vue 项目的根目录下执行以下命令: ``` npm install electron-builder --save-dev ``` 2. 配置打包参数 在项目目录下创建一个 electron-builder.json 文件,用于配置打包参数。可以参考 electron-builder 的文档进行配置,主要包括应用程序名称、版本号、图标等。 3. 执行打包命令 在项目目录下执行以下命令进行打包: ``` npm run build:win ``` 该命令会生成一个 dist 目录,其中包含打包后的应用程序和安装程序,可以在 Windows 上运行。 以上就是将 electron-vue 项目打包成 exe 的基本步骤,希望对你有帮助。 ### 回答2: electron-vue 是基于 Vue.js 和 Electron 的开发框架,可以快速构建桌面应用程序。在开发完成后,开发者需要将其打包成 .exe 格式(Windows 可执行文件),以便部署和发布。 以下是将 electron-vue 项目打包成 .exe 文件的步骤: 1. 准备工作 首先要安装 electron-packager 包,这个包可以让我们快速打包 electron 应用程序。可以在终端中输入以下命令进行安装: npm install electron-packager --save-dev 2. 修改 package.json 文件 在 package.json 文件中,需要添加以下代码: "scripts": { "package": "electron-packager ./ --platform=win32 --arch=x64 --icon=./build/icons/icon.ico --out=./dist --ignore=dist --overwrite" } 这个代码段是一个命令,运行它可以将项目打包成指定平台(这里是 win32,也就是 Windows)的可执行文件,以 .exe 格式输出到指定目录(这里是 dist 文件夹)。其中,--icon 表示程序图标,--ignore 是忽略打包的文件夹,--overwrite 表示覆盖已有的输出文件夹。 3. 执行打包命令 在终端中输入以下命令,即可开始打包: npm run package 然后等待一段时间,打包成功之后会在 dist 目录下生成 .exe 文件。 4. 发布 最后将 .exe 文件上传到合适的平台(例如 GitHub Release),这样用户就可以下载并使用了。 注意事项: - 在打包时需要注意修改 .ico 图标文件路径,确保能正确找到。 - 若需要打包成其他平台的可执行文件,可以修改 --platform 和 --arch 参数。 - 打包时,如果报错了,可以在命令行加上 --verbose 参数,查看具体错误信息。 ### 回答3: electron-vue是一个基于vue.js构建的 electron框架的项目,可以让开发者快速地构建跨操作系统的桌面应用程序,并且electron-vue项目也非常容易打包成exe可执行文件,便于在Windows平台上使用。 打包electron-vue项目成exe的方法: 首先要在命令行中进入项目目录, 然后运行: npm run build 或 yarn run build 这两个命令将会编译和打包electron-vue项目,生成一个dist目录。 在默认情况下,打包出的exe应用程序是没有图标的,如果需要添加图标,需要在build目录下找到win下的icon.ico文件,并替换成你自己的图标文件。 接下来,需要使用第三方的打包工具,如electron-builder,打包成exe文件,命令如下: npm run dist 或 yarn run dist 执行完这个命令后,就会在dist目录下生成一个installer目录,里面包含着生成的exe文件和其他必要的文件。 理论上,exe应用程序已经可以在Windows平台上使用了。 总结: electron-vue项目打包成exe并不是一件复杂的事情。只需进入项目目录运行 npm run build 命令,然后使用第三方打包工具electron-builder打包,就可以生成一个可执行的exe文件了,这样就极大地方便了开发者在Windows平台上部署应用程序。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值