You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Electron应用如何实现多XLSX文件上传保存至本地指定目录

Electron本地多XLSX文件上传存储实现方案

你之前尝试的Web端常规文件上传方案无法写入本地,是因为Electron渲染进程默认处于沙箱环境,没有直接操作系统文件的权限,通过IPC通道将文件数据传递给主进程,用Node.js原生fs模块写入即可实现需求,完整实现步骤如下:

1. 前置配置

首先在项目中配置preload脚本,在保持Electron安全默认配置的前提下,给渲染进程暴露必要的文件操作API,不要直接关闭上下文隔离、开启渲染进程Node权限,避免安全风险。
在项目根目录新建preload.js,写入以下代码:

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

contextBridge.exposeInMainWorld('electronAPI', {
  saveXlsxFiles: (files) => ipcRenderer.invoke('save-xlsx-files', files),
  getStorageDir: () => path.join(__dirname, 'uploaded_xlsx')
})

2. 主进程实现存储逻辑

在主进程文件(通常是main.js)中实现目录自动创建、文件格式校验、文件写入逻辑,存储路径固定为应用目录下的uploaded_xlsx文件夹,适配开发环境和打包后的生产环境路径差异:

// main.js
const { app, ipcMain, BrowserWindow } = require('electron')
const fs = require('fs/promises')
const path = require('path')

let mainWindow
// 固定存储路径:打包后为可执行文件同级的uploaded_xlsx,开发环境为项目根目录下的uploaded_xlsx
const STORAGE_DIR = app.isPackaged
  ? path.join(path.dirname(app.getPath('exe')), 'uploaded_xlsx')
  : path.join(__dirname, 'uploaded_xlsx')

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false
    }
  })
  mainWindow.loadFile('index.html')
}

app.whenReady().then(async () => {
  // 启动时自动检查存储目录,不存在则创建
  try {
    await fs.access(STORAGE_DIR)
  } catch {
    await fs.mkdir(STORAGE_DIR, { recursive: true })
  }
  createWindow()
})

// 监听渲染进程的文件保存请求
ipcMain.handle('save-xlsx-files', async (_, fileList) => {
  const results = []
  for (const file of fileList) {
    // 校验文件格式,仅允许xlsx
    if (path.extname(file.name).toLowerCase() !== '.xlsx') {
      results.push({ filename: file.name, success: false, msg: '仅支持.xlsx格式文件' })
      continue
    }
    // 处理同名文件,自动加时间戳后缀避免覆盖
    let targetPath = path.join(STORAGE_DIR, file.name)
    try {
      await fs.access(targetPath)
      const ext = path.extname(file.name)
      const baseName = path.basename(file.name, ext)
      targetPath = path.join(STORAGE_DIR, `${baseName}_${Date.now()}${ext}`)
    } catch {}
    // 写入文件到本地
    try {
      await fs.writeFile(targetPath, Buffer.from(file.buffer))
      results.push({ filename: file.name, success: true, path: targetPath })
    } catch (err) {
      results.push({ filename: file.name, success: false, msg: err.message })
    }
  }
  return results
})

3. 渲染进程实现文件选择交互

在你已经写好的HTML页面中添加多文件选择控件,选完文件后将文件读取为ArrayBuffer格式,通过preload暴露的API传给主进程保存即可:

<!-- 页面上传区域 -->
<input type="file" id="xlsxPicker" accept=".xlsx" multiple>
<button id="submitUpload">上传文件</button>
<div id="uploadStatus"></div>
// 渲染进程JS逻辑
const picker = document.getElementById('xlsxPicker')
const submitBtn = document.getElementById('submitUpload')
const statusDom = document.getElementById('uploadStatus')

submitBtn.addEventListener('click', async () => {
  const selectedFiles = picker.files
  if (!selectedFiles.length) {
    statusDom.innerText = '请先选择需要上传的XLSX文件'
    return
  }
  // 读取文件为二进制数据
  const fileData = []
  for (const file of selectedFiles) {
    const buffer = await file.arrayBuffer()
    fileData.push({ name: file.name, buffer })
  }
  // 传给主进程保存
  const uploadResults = await window.electronAPI.saveXlsxFiles(fileData)
  // 展示上传结果
  let statusText = '上传完成:\n'
  uploadResults.forEach(res => {
    statusText += `${res.success ? '✅' : '❌'} ${res.filename}:${res.success ? '已存储至指定目录' : res.msg}\n`
  })
  statusDom.innerText = statusText
})

注意事项

  • 所有路径拼接使用Node.js的path模块,不要手动写路径斜杠,自动适配Windows、macOS的路径规则
  • 你已经开发完成的作业管控逻辑,直接读取STORAGE_DIR对应路径下的文件即可,所有上传的XLSX都会固定存在该目录,项目成员可直接访问该路径获取文件
  • 如果打包后出现目录写入报错,给应用所在文件夹开放当前用户的读写权限即可,开发环境运行无权限问题

内容的提问来源于stack exchange,提问作者Gregi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:42:17