详解如何在Electron中存取本地文件

 更新时间:2023年11月30日 10:08:26   作者:Sean  
在Electron 中,存取本地文件,有很多种办法,本文介绍最常用的一种办法, 通过 Electron 框架提供的能力,和 Node.js 的 fs 文件管理模块实现本地文件的存取,需要的小伙伴可以参考下

最近在使用 Electron 做一个手写字体生成图片的工具。 不可避免的,遇到了通过Electron 往本地存文件的问题。

在Electron 中,存取本地文件,有很多种办法。本文介绍最常用的一种办法。 通过 Electron 框架提供的能力,和 Node.js 的 fs 文件管理模块实现本地文件的存取。

使用 app.getPath 和 fs 模块存储文件

首先,我们可以通过 app.getPath 来获取当前用户的 data 存放目录。

app.getPath(’userData’) 返回一个字符串,该字符串表示应用程序的用户数据目录的路径。这个目录通常是用来存储用户相关的数据,例如配置文件、缓存等。具体路径会根据操作系统而变化。

  • windows 系统中, 会返回类似(C:\Users\<username>\AppData\Roaming\<YourAppName>)这样的结果。
  • Mac 系统中,会返回(/Users/<username>/Library/Application Support/<YourAppName>) 这种结果。
  • linux 系统中 则会返回 (/home/<username>/.config/<YourAppName>) 这种结果。

我们通过 node.js 的path 模块, 使用 path.join(app.getPath('userData'), 'myFile.txt') 就能得到一个完整的文件路径。 接着使用 fs 模块的 来写入内容即可。

示例代码如下:

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

const filePath = path.join(app.getPath('userData'),'/myfile.txt'); // Example file path

try {
   fs.writeFileSync(filePath, 'hello world', 'utf-8');
} catch (e) {
   console.error('Failed to save the file!');
}

这种做法,有一个问题。那就是,用户不能在保存的时候,主动选择文件存放目录。

使用 Dialog API 和 fs 模块配合

Electron 提供了一个 Dialog API 来处理文件对话框。您可以专门调用一个保存对话框,让用户选择保存文件的位置。

下面是一个简单的,示例代码:

const {
   dialog
} = require('electron').remote;
const fs = require('fs');

const options = {
   title: 'Save file',
   defaultPath: 'my_filename',
   buttonLabel: 'Save',
   filters: [{
         name: 'txt',
         extensions: ['txt']
      },
      {
         name: 'All Files',
         extensions: ['*']
      },
   ],
};

dialog.showSaveDialog(null, options).then(({
   filePath
}) => {
   if (filePath) {
      fs.writeFileSync(filePath, 'hello world', 'utf-8');
   }
});

需要注意的点:

因为 fs 模块 和 Dialog 只能在,主进程中被调用。 但是我们的应用程序交互逻辑是在渲染进程,所以这段示例代码,只是演示了,如何去调用 Dialog 并手动选择文件存储位置。 并没有实际应用场景的参考意义。

实际应用场景封装 调整

对存取图片的封装想法跟之前的采集桌面思路基本一致(如果,没看过可以翻一下以前的文章)。 我们利用 Electron 的 ipcmain 模块在主进程中注册方法。 然后,在渲染进程去调用。 整理实现流程大概如下图所示。

实例代码:

// 主进程 ->  main.js

// .... ohter code
// ... 在主进程注册我们封装后的 SaveFile 方法
const { app, BrowserWindow, ipcMain, dialog} = require("electron");
const path = require("path");
const fs = require('fs');

/**
 * @param options: { title:  String, defaultPath: String, buttonLabel: String, filters: area}
 * @param content: String
 * @returns Promise
 */
ipcMain.handle('saveFile', async (event, content, options) => {
  let path;
  try {
  const { filePath } =  await dialog.showSaveDialog(null, options);
    path = filePath;
  } catch(e) {
    return Promise.reject({error: e, success: false});
  }
  if(path) {
    try {
      fs.writeFileSync(path, content, 'utf-8');
      return Promise.resolve({error: null, success: true});
    } catch(e) {
      return Promise.reject({error: e, success: false});
    }
  } else {
    return Promise.reject({error: e, success: false, canceled: true});
  }
});

// 其他代码 ....
// Vue 文件、
// 在我们,的Vue 业务中。直接通过 ipc 调用

<script setup>
  import {reactive, ref, onMounted} from "vue";
  const textContent = ref('hello world');
  const { ipcRenderer } = require('electron');

  const exportImg = async () => {
    try {
            // 注意->  第一个参数,为 主进程注册进来的方法名称。 
      // 其他参数为, 主进程注册的函数参数。
      await ipcRenderer.invoke('saveFile', 'hello', {
        title: '导出图片',
        buttonLabel: '导出',
        defaultPath: 'text.txt',
        filters: [{
         name: 'All Files',
         extensions: ['*']
          }]
      })
    } catch(e) {
      console.error('出错了!', e)
    }
  }
</script>
<template>
    <a-config-provider :csp="{ nonce: 'YourNonceCode' }">
      <a-button type="primary" @click="exportImg">导出</a-button>
  </a-config-provider>
</template>

总结

在Electron 中,向本地存储和读取文件(文本或者是图片), 都离不开 node.js 的 fs 模块, 这个是文件系统处理的核心模块。

然后,我们搭配, path 模块。 dialog 模块,可以实现,用户主动选择存放位置。 或者 直接存到默认软件系统的 data 目录中。

当然,这些模块都只能在主进程中使用。 所以,我们不可避免的用到了, 之前的老朋友, ipc 进程间通讯方式。

到此这篇关于详解如何在Electron中存取本地文件的文章就介绍到这了,更多相关Electron存取本地文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解vue 2.6 中 slot 的新用法

    详解vue 2.6 中 slot 的新用法

    对插槽的这种改变让我对发现插槽的潜在功能感兴趣,以便为我们基于Vue的项目提供可重用性,新功能和更清晰的可读性。这篇文章主要介绍了vue 2.6 中 slot 的新用法,需要的朋友可以参考下
    2019-07-07
  • 详解Vue自定义过滤器的实现

    详解Vue自定义过滤器的实现

    这篇文章主要介绍了详解Vue自定义过滤器的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧。
    2017-01-01
  • vue+tp5实现简单登录功能

    vue+tp5实现简单登录功能

    这篇文章主要为大家详细介绍了vue+tp5实现简单登录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • vuex 动态注册方法 registerModule的实现

    vuex 动态注册方法 registerModule的实现

    这篇文章主要介绍了vuex 动态注册方法 registerModule的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • Vue之事件处理和事件修饰符详解

    Vue之事件处理和事件修饰符详解

    这篇文章主要为大家介绍了Vue之事件处理和事件修饰符,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助<BR>
    2021-11-11
  • Vue 防止短时间内连续点击后多次触发请求的操作

    Vue 防止短时间内连续点击后多次触发请求的操作

    这篇文章主要介绍了Vue 防止短时间内连续点击后多次触发请求的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • 详解vue-cli下ESlint 配置说明

    详解vue-cli下ESlint 配置说明

    这篇文章主要介绍了详解vue-cli下ESlint 配置说明,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • vue打包添加gzip配置项方式

    vue打包添加gzip配置项方式

    这篇文章主要介绍了vue打包添加gzip配置项方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • vue.js Router中嵌套路由的实用示例

    vue.js Router中嵌套路由的实用示例

    这篇文章主要给大家介绍了关于vue.js Router中嵌套路由的相关资料,所谓嵌套路由就是路由里面嵌套他的子路由,文章通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-06-06
  • vue3中使用jsx的实现步骤

    vue3中使用jsx的实现步骤

    本文主要介绍了vue3中使用jsx的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07

最新评论