Download always interrupted when downloading from electron main process

Viewed 140

I have a desktop app I'm building with electron. The UI hits a flask server I have running on local host and tries to download a file. I cannot figure out why the download always immediately enters an "interrupted" state. The backend server is never even hit so I suspect the problem has something to do with my electron configuration.

Below is a minimal working example that triggers the problem. Most of the code is boilerplate lifted from other sources.

main.js

const {app, BrowserWindow, ipcMain, shell} = require('electron')
const path = require('path')

let mainWindow;
function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadFile('index.html')

}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })

  ipcMain.on('download-file', async (event, properties) => {
    console.log(`Downloading ${properties.link}`)

    mainWindow.webContents.downloadURL(`${properties.link}`)

    mainWindow.webContents.session.on('will-download', (event, item, webContents) => {

      item.setSavePath(`${path.resolve(app.getPath("appData"), properties.filename)}`)
      item.on('updated', (event, state) => {
        if (state === 'interrupted') {
          console.log('Download interrupted but can be resumed')
        } else if (state === 'progressing') {
          if (item.isPaused()) {
            console.log("Item is paused")
          } else {
            console.log(`Recieved bytes ${item.getReceivedBytes()}`)
          }

        }
      })

      item.once('done', (event, state) => {
        if (state === 'completed') {
          console.log("Downloaded successfully")
          shell.openItem(item.getSavePath())
        } else {
          console.log(`Download failed ${state}`)
        }
      })
    });
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

preload.js

const {ipcRenderer, contextBridge} = require('electron')

window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

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

contextBridge.exposeInMainWorld('electron', {
  download() {
    ipcRenderer.send('download-file', {link: "http://127.0.0.1:5000/file/test.txt", filename: "test.txt"})
  }
})

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
    <link href="./styles.css" rel="stylesheet">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <input type="button" value="Download" id="downloadButton">

    <script src="./renderer.js"></script>
  </body>
</html>

renderer.js

const download = window.electron.download

document.getElementById("downloadButton").onclick = download;

EDIT: Of course it turns out the backend was the problem. The file being requested didn't exist. Ignore this question

0 Answers
Related