diff --git a/runtime/src/js/downloader.js b/runtime/src/js/downloader.js index 1aa9c1617..58413e4f3 100644 --- a/runtime/src/js/downloader.js +++ b/runtime/src/js/downloader.js @@ -63,25 +63,29 @@ function updateProgress(callerWindow) { setProgress.call(callerWindow, progress); } +async function fileDownloadPath(callerWindow, options, prompt=true) { + let filePath = path.join(app.getPath('downloads'), options.defaultPath); + // prompt is true when the user has set the preference to prompt for download location + if(prompt) { + const result = await dialog.showSaveDialog(callerWindow, { + title: 'Save File', + ...options, + }); + + if (result.canceled) { + return; + } + filePath = result.filePath; + } + return filePath; +} + export function setupDownloader() { // Listen for the renderer's request to show the open dialog ipcMain.handle('get-download-path', async (event, options, prompt=true) => { try { - let filePath = path.join(app.getPath('downloads'), options.defaultPath); const callerWindow = BrowserWindow.fromWebContents(event.sender); - // prompt is true when the user has set the preference to prompt for download location - if(prompt) { - const result = await dialog.showSaveDialog(callerWindow, { - title: 'Save File', - ...options, - }); - - if (result.canceled) { - return; - } - filePath = result.filePath; - } - + const filePath = await fileDownloadPath(callerWindow, options, prompt); downloadQueue[filePath] = new DownloadItem(filePath, () => { updateProgress(callerWindow); }, () => { @@ -118,4 +122,13 @@ export function setupDownloader() { openFile && shell.openPath(filePath); } }); + + // non-streaming direct download + ipcMain.handle('download-base64-url', async (event, base64url, options, prompt=true, openFile=false) => { + const callerWindow = BrowserWindow.fromWebContents(event.sender); + const filePath = await fileDownloadPath(callerWindow, options, prompt); + const buffer = Buffer.from(base64url.split(',')[1], 'base64'); + fs.writeFileSync(filePath, buffer); + openFile && shell.openPath(filePath); + }); } \ No newline at end of file diff --git a/runtime/src/js/pgadmin_preload.js b/runtime/src/js/pgadmin_preload.js index 6541aac74..240c96a32 100644 --- a/runtime/src/js/pgadmin_preload.js +++ b/runtime/src/js/pgadmin_preload.js @@ -29,4 +29,5 @@ contextBridge.exposeInMainWorld('electronUI', { downloadDataSaveChunk: (...args) => ipcRenderer.send('download-data-save-chunk', ...args), downloadDataSaveTotal: (...args) => ipcRenderer.send('download-data-save-total', ...args), downloadDataSaveEnd: (...args) => ipcRenderer.send('download-data-save-end', ...args), + downloadBase64UrlData: (...args) => ipcRenderer.invoke('download-base64-url', ...args) }); \ No newline at end of file diff --git a/web/pgadmin/static/js/download_utils.js b/web/pgadmin/static/js/download_utils.js index 26886cd31..2114446df 100644 --- a/web/pgadmin/static/js/download_utils.js +++ b/web/pgadmin/static/js/download_utils.js @@ -14,6 +14,15 @@ import { getBrowser, toPrettySize } from './utils'; // This function is used to download the base64 data // and create a link to download the file. export async function downloadBase64UrlData(downloadUrl, fileName) { + if(getBrowser().name == 'Electron') { + const {automatically_open_downloaded_file, prompt_for_download_location} = usePreferences.getState().getPreferencesForModule('misc'); + // In Electron, we use the electronUI to download the file. + await window.electronUI.downloadBase64UrlData(downloadUrl, { + defaultPath: fileName, + }, prompt_for_download_location, automatically_open_downloaded_file); + return; + } + // In other browsers, we create a link to download the file. let link = document.createElement('a'); link.setAttribute('href', downloadUrl); link.setAttribute('download', fileName);