使用 ElectronJS 将 blob 保存到文件

问题描述 投票:0回答:1

我正在尝试升级我的 Electron 应用程序,但没有节点集成和上下文隔离。我正在将文件保存代码从渲染器移至主进程。但是,我无法将 blob 传输到主进程。

错误信息是:

Uncaught (in promise) Error: An object could not be cloned.

main.js

const {app, BrowserWindow, dialog, ipcMain } = require('electron');
const path = require("path");
const fs = require("fs");
    
if (require('electron-squirrel-startup')) return app.quit();
    
try {require('electron-reloader')(module);} catch (_) {}
   
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
    
async function createWindow() {
    
    // Create the browser window.
    win = new BrowserWindow({
        width: 1024,
        height: 768,
        webPreferences: {
            preload: path.join(__dirname, "preload.js") // use a preload script
        },
        autoHideMenuBar: true,
        icon: __dirname + '/icons/icon.icns'
    });
    
    // and load the index.html of the app.
    win.loadFile('index.html')
    
    // Open the DevTools.
    win.webContents.openDevTools()    
}
    
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
    createWindow();
    
    ipcMain.handle('dialog', (event, method, params) => {
        return dialog[method](params);
    });
  
    ipcMain.handle('getPath', () => {
        app.getPath('documents');
    });
    
    ipcMain.handle('writeFile', (event, filepath, blob) => {
        var message = {};
        fs.writeFile(filepath, blob, err => {
            if (err) {
                message.text = err;
                message.title = 'Error Saving Table';
            } else {
                message.text = filepath;
                message.title = 'Table saved to';
            }
        });
        return message;
    });
});

预加载.js

const {
    ipcRenderer,
    contextBridge
} = require("electron");
    
contextBridge.exposeInMainWorld('electron', {
    openDialog: (method, params) => ipcRenderer.invoke('dialog', method, params),
    getPath: () => ipcRenderer.invoke('getPath'),
    writeFile: (filepath, blob) => ipcRenderer.invoke('writeFile', filepath, blob)
});

渲染器.js

function exportToExcelFile(tableID, anchorID, exportFilename) {
    let format = 'xlsx';
    let anchor = $$('#' + anchorID + '-' + format);
    ExcellentExport.convert({
            anchor: anchor[0],
            filename: exportFilename,
            format: format
        }, [{
            name: 'Sheet1',
            from: {
                table: $$('#' + tableID)[0]
            }
    }]);
    
    // Get path, open save dialog and save file
    window.electron.getPath()
        .then((appDataPath) => {
            const dialogConfig = {
                filters: [{
                    name: 'Excel',
                    extensions: ['xlsx']
                }],
                defaultPath: appDataPath + '/' + exportFilename
            };
            electron.openDialog('showSaveDialogSync', dialogConfig).then(
                filepath => {
                    if (filepath !== undefined) {
                        console.log(anchor.attr('href'));
                        fetch(anchor.attr('href'))
                            .then(res => res.blob())
                            .then(blob => {electron.writeFile(filepath, blob);
                                    })
                            .then(message => {app.dialog.alert(message.text, message.title);
                            })
                    }
                }
            );
        })
        .catch(result => console.log(result));
}
electron blob
1个回答
0
投票

您无法通过 IPC 将 Blob 从渲染器发送到主程序,在此之前您必须将其转换为 ArrayBuffer。

当你在 main 上收到 ArrayBuffer 后,为了能够将其写入文件系统,你必须将其转换为 Node.js 的全局 Buffer。

// renderer
const arrayBuffer = await blob.arrayBuffer()
ipcRenderer.send('save-blob', arrayBuffer)
// main
const buffer = Buffer.from(arrayBuffer)
fs.writeFile(filePath, buffer)

(您也可以使用 FileReader API 将 ArrayBuffer 直接从渲染器进程转换为 Buffer,然后将其发送到 main,这样就可以直接写入文件系统)

© www.soinside.com 2019 - 2024. All rights reserved.