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
相关产品推荐
相关产品推荐

