Electron中如何安全地读取本地文件系统?

Mr.世英 阅读 63

我在用Electron做个小工具,想读取用户选中的本地文件内容,但直接用fs.readFileSync在渲染进程里报错说“require is not defined”,这咋整?

我试过在主进程里加了nodeIntegration: true,但听说不安全。现在想用预加载脚本暴露有限的文件操作接口,但样式部分又出问题了——比如下面这段CSS在加载本地图片时完全失效:

.file-preview {
  background-image: url('file:///C:/Users/test/image.png');
  width: 200px;
  height: 150px;
  background-size: cover;
}

是不是因为Electron的安全策略阻止了file协议访问?该怎么正确处理本地文件的读取和显示啊?

我来解答 赞 6 收藏
二维码
手机扫码查看
2 条解答
宇文淑芳
这个问题挺常见的,Electron的安全机制确实让新手有点头疼。我来帮你理一理。

渲染进程读不了fs的问题

不能用nodeIntegration: true,确实不安全。正确做法是通过预加载脚本暴露有限接口。

主进程代码里这样处理:

// main.js
const { ipcMain } = require('electron');
const fs = require('fs');

ipcMain.handle('read-file', async (event, filePath) => {
try {
const data = fs.readFileSync(filePath);
return { success: true, data: data.toString('base64') };
} catch (error) {
return { success: false, error: error.message };
}
});


// preload.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath)
});


渲染进程里这样调用:

// 渲染进程
const result = await window.electronAPI.readFile('C:/Users/test/image.png');
if (result.success) {
const img = document.querySelector('.file-preview');
img.style.backgroundImage = url(data:image/png;base64,${result.data});
}


关于CSS里file://协议失效的问题

Electron确实限制了file协议直接访问。上面那个转base64的方案就能解决问题。

如果你只是想读文本文件,同样逻辑:

// 主进程
ipcMain.handle('read-text-file', async (event, filePath) => {
const content = fs.readFileSync(filePath, 'utf-8');
return content;
});


渲染进程拿到的就是纯文本内容了。

核心思路就是这样:渲染进程别直接操作fs,通过预加载脚本搭个桥,让主进程帮忙读文件,然后以安全的方式(base64或者文本)传回渲染进程。
点赞
2026-03-14 08:10
UP主~国凤
这个问题其实两部分:JS读取文件和CSS显示本地图片。

先说JS读取文件。渲染进程确实不能直接用fs,得靠预加载脚本搭桥。核心思路是通过contextBridge暴露有限接口,而不是开nodeIntegration——后者确实不安全,相当于把整个Node.js能力暴露给网页。

预加载脚本这样写:

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

contextBridge.exposeInMainWorld('fileAPI', {
readTextFile: (filePath) => ipcRenderer.invoke('read-text-file', filePath),
readImageAsBase64: (filePath) => ipcRenderer.invoke('read-image-base64', filePath)
});


主进程处理:

const { ipcMain } = require('electron');
const fs = require('fs').promises;

ipcMain.handle('read-text-file', async (event, filePath) => {
return await fs.readFile(filePath, 'utf-8');
});

ipcMain.handle('read-image-base64', async (event, filePath) => {
const buffer = await fs.readFile(filePath);
const ext = filePath.split('.').pop();
return data:image/${ext};base64,${buffer.toString('base64')};
});


渲染进程调用:

const content = await window.fileAPI.readTextFile('C:/Users/test/data.txt');
console.log(content);




再说CSS加载本地图片的问题。直接写file://协议在Electron里确实不太稳定,更靠谱的写法是通过base64数据URL:

const imgData = await window.fileAPI.readImageAsBase64('C:/Users/test/image.png');
document.querySelector('.file-preview').style.backgroundImage = url(${imgData});


或者如果你用的是img标签:

const imgData = await window.fileAPI.readImageAsBase64('C:/Users/test/image.png');
document.getElementById('preview').src = imgData;


这样搞的好处是统一走IPC通道,安全性可控,不会因为file协议的各种限制踩坑。
点赞 1
2026-03-12 04:04