background
After the front end clicks the export excel button, it requests the data to be exported and sends it to the main process, electron, which saves it locally
dialog
Displays native system dialog boxes for opening and saving files, alarms, and so on.
The dialog module provides an api to show the native system dialog box, such as open file box and alert box, so web application can bring the same experience as system application to users
let win = ...; // BrowserWindow in which to show the dialog const dialog = require('electron').dialog; console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
Front end code (rendering process)
// Introducing ipcRenderer module const { ipcRenderer } = require('electron') // Table data is proposed as data let excelModel = new Blob([data], { type: "application/octet-stream" })
I don't know what Blob is. Click here
// Create an instance of FileReader let reader = new FileReader() // Starts reading from the specified Blob. Once completed, the result property will contain a Base64 string in the format of data: URL to represent the contents of the read file. reader.readAsDataURL(excelModel) // Handle the load event. This event is triggered when the read operation completes reader.addEventListener("loadend", function() { // reader.result contains blob s converted to type array // Send download excel message to main process ipcRenderer.send("saveDialog", { baseCode: reader.result, fileType: 'excel', fileName: 'Fengshen Bang' }) // Receive the download success callback sent back by the main process ipcRenderer.once('succeedDialog', event => { // Successful callback }) // Receive the download failure callback sent back by the main process ipcRenderer.once('defeatedDialog', event => { // Failed callback }) })
I don't know what FileReader is. Click here
electron code (main process)
// Create BrowserWindow instance let win = new BrowserWindow(browser) // Introduce dialog, ipcMain and fs modules const { dialog, ipcMain } = require('electron') const fs = require('fs') // Define file download extension selection const extensionType = { // picture images: [ { name: '.jpg', extensions: ['jpg'] }, { name: '.png', extensions: ['png'] }, { name: '.gif', extensions: ['gif'] }, ], // Excel excel: [ { name: '.xlsx', extensions: ['xlsx'] }, { name: '.xls', extensions: ['xls'] }, ] } //Under the main thread, listen for the saveDialog event from the rendering thread through the ipcMain object ipcMain.on('saveDialog', (event, arg) => { // Open the window dialog.showSaveDialog(win, { // On Windows and Linux, the open dialog box cannot be both a file selector and a directory selector, so if you set properties to ["openFile", "openDirectory"] on these platforms, it will be displayed as a directory selector. properties: ['openFile', 'openDirectory'], // Absolute directory path, absolute file path, and file name used by default defaultPath: arg.fileName, // File download extension filters: [ ...extensionType[arg.fileType] ], // Click Save callback }, filePath =>{ // Save path if filePath exists or undefined // Remove the useless fields in the header and transcode base64 to buffer let dataBuffer = Buffer.from(arg.baseCode.split('base64,')[1], 'base64') // Check if the file extension is correct let typeFlag = extensionType[arg.fileType].some(item => { if(filePath) { return item.extensions[0] === filePath.split('.')[1] } else { return false } }) if(typeFlag){ fs.writeFile(filePath, dataBuffer, err => { // fail if (err) { // Failed to send message notification to rendering process win.webContents.send('defeatedDialog') } }) // Successfully sent message notification to rendering process win.webContents.send('succeedDialog') // Determine whether there is a saving path } else if(filePath !== undefined){ dialog.showMessageBox({ type: 'error', title: 'System hint', message: 'The system has detected that the file type is abnormal. Please check and re select or fill in' }) } }) })
The reason why the extension of the file is judged again after confirmation is that the extension of the file passed into excel can still save other extensions, such as. jpg. The specific reason is not clear to the author. It will be updated later...
The above is for reference only. If you have any questions, please point out, but I don't necessarily change (~ ▽) ~
Reference resources
recorderJs in electron exports the blob object and uses node to save it locally