loading...

What are the options to download a file in Electron based applications?

alirezavalizade profile image alireza valizade Originally published at Medium on ・4 min read

If you want to deal with downloading files, better read this before start coding 🙌

My own downloader, will be live soon 🔥the icons are fake for now 😀

I was developing an Electron application a while ago and one of the challenges was downloading files and did some researches about it and saw that the Electron download API wasn’t the only option and it was tricky to use. 🤔

If your project is growing fast and the future is important for you, Then you need to think about every thing before any actions. An action could be choosing a library or framework or installing a simple package from npmjs. You should think about the consequences and be independent. 😀

Here are some topics and questions you may need ask yourself before start coding:

Has or Will have my application a website version? Like Slack. Just renderer code base and ignoring the native dependencies.

Yeah. This is important thing when you have to deal with files and buffers in your application. You should also consider the web version in the client side there is not main process and there is no IPC module to communicate through the channels. Like so:

// somewhere in main process
const window = "Your browser window instance";

ipcMain.on('download-url', (event, url) => {
  download(url);  
});

// somewhere in renderer process
ipcRenderer.send('download-url', "https://google.com/dummy.mp4");

Don’t depend your app to main process which won’t be there in website version. Keep the renderer process isolate as much as you can and reduce the dependencies.

There are lots of solutions in renderer (Browser), you can use simple or fetch Api or third party libraries. You can get buffer or blob using fetch which is what you need.

const download = async (url) => {
  const response = await fetch(url);
  const file = await response.blob();
  console.log(file);
};

Note: You can use remote module here to control the file system.

Electron download api is stupid, check out this issue on electron’s repository. You can’t even send custom headers!

Do i need to show progress/status on each download item?

Well this depends on the UI, Electron’s downloadItem has cool features which you can get the progress and received bytes but that’s not enough! There are a lot of options, You can handle this in both processes. You can use built-in http module or third party packages request which is same but simplified version. In the renderer is same thing, Let’s look at an example from javascript.info

This is what you need to show the progress/status on downloading items. also will work on the browser, so you’re not depend on the main process.

Do i need to have actions? (Cancel, Pause, Resume)

This is also easy to do, you can use the electron downloader api, but there’re few issues for example if you want to cancel an downloading item it’s easy but after restarting the app or losing the download item you won’t be able to resume it. another issue is it cannot be customized even setting simple header. This was the one may things which decided to go for the renderer or another method to use as downloader helper.

You can use fetch api in renderer to cancel, pause and also resume the download item. you can easy set aRange property header to your downloader which is based onfetch . This is how the streaming services are working like Spotify or Netflix. You can specify which part of file you want to download. Then you can merge the downloader buffer to new or cached buffer in disk suing file-system api or IndexedDB in renderer.

for cancelling also fetch has nice and easy way to cancel the request.

Spotify 🎺

You want a challenge? Now you can create a multipart file downloader. Doesn’t matter which api, try fetch or axios or anything in Javascript🔥

Is concurrency important for you regarding the performance in the renderer in case you need to show report for each one, and network speed?

You can try and create and async queue which accepts number of concurrency . I’d recommend you to use async.queue.

Summing up

I’m very positive about the future of the developing cross-platform/web applications and it’s growing fast and I think this was the one of interesting topics to know. I couldn’t find what I was looking for in one article so that was the reason I wrote this one. Hope you enjoyed it. ❤️

Thanks for reading, If there is anything I have missed, or if there is a better way to do something, Then please let me know. 🤙

You can find me on Github and Twitter!

Discussion

markdown guide