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

Electron中如何将Renderer进程的WAV Blob发送到Main进程保存到磁盘?

问题描述

我在Electron项目中编写了以下代码,尝试将渲染进程中的audio/wav类型Blob发送到主进程并保存到磁盘,但目前无法正确保存:

preload.js 代码

const { contextBridge, ipcRenderer } = require('electron')
// Toutes les API Node.js sont disponibles dans le processus de préchargement.
// Il a la même sandbox qu'une extension Chrome.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }

})
contextBridge.exposeInMainWorld(
"api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["fromMain",'fromparam'];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender` 
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        },
        contextmenu: (channel, data) => {
            // whitelist channels
            let validChannels = ["showmenu"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel,'showmenu')
            }
        }
    }
)

渲染进程(index.html)发送代码

window.api.send("toMain", "saveAudioObjet;"+(audioDirectory+"exports/"+tableObjet[obj].id+".wav")+";"+blob) 

主进程(main.js)保存函数

function saveAudioObjet(dest,buf) {
 fs.writeFile(dest, 
        Buffer.from(buf), function (err) {
            if (err) throw err;
            console.log('Saved!')
        })
}

现在需要解决如何将Blob正确保存到磁盘的问题。


解决方案

核心问题是直接将Blob对象拼接成字符串传递会导致数据丢失,需要通过IPC支持的格式传递Blob原始数据,以下是具体修改步骤:

1. 修改渲染进程的发送逻辑

不要拼接字符串,先将Blob转为ArrayBuffer(Electron的IPC支持传递该类型),再传递包含操作信息的对象:

// 转换Blob为ArrayBuffer后发送
blob.arrayBuffer().then(arrayBuffer => {
  window.api.send("toMain", {
    action: "saveAudioObjet",
    dest: audioDirectory + "exports/" + tableObjet[obj].id + ".wav",
    buffer: arrayBuffer
  });
});

2. 主进程修改监听与保存逻辑

在main.js中解析IPC传递的对象,将ArrayBuffer转为Node.js的Buffer后写入文件,同时确保目标目录存在:

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

// 监听toMain通道
ipcMain.on("toMain", (event, data) => {
  if (data.action === "saveAudioObjet") {
    saveAudioObjet(data.dest, data.buffer);
  }
});

function saveAudioObjet(dest, arrayBuffer) {
  // 将ArrayBuffer转为Node.js可识别的Buffer
  const buffer = Buffer.from(arrayBuffer);
  // 递归创建目标目录(避免目录不存在导致写入失败)
  const dir = path.dirname(dest);
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  // 写入文件
  fs.writeFile(dest, buffer, (err) => {
    if (err) {
      console.error("音频保存失败:", err);
      return;
    }
    console.log('音频已保存至:', dest);
  });
}

3. 确认preload配置(无需修改)

当前preload的send方法已经支持传递对象,只需确保toMain在白名单中即可,无需额外调整。


关键说明

  • Blob不能直接通过IPC传递,必须转为ArrayBuffer才能保证数据完整性
  • 主进程需要将ArrayBuffer转为Node.js的Buffer类型,才能通过fs.writeFile写入磁盘
  • 写入前务必检查并创建目标目录,避免因目录不存在导致保存失败

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 20:53:11