Comments (9)
I spent a fair amount of time looking into this tonight and it seems that there's just no good way to handle simultaneous downloads. registerListener
is going to create multiple listeners for 'will-download'
and then when the downloads complete multiple listeners will be getting the callback and it becomes a whole mess, and all downloads get saved under the same file name, progress gets screwed up etc. Maybe there's a solution, but I couldn't figure one out.
What I did was make it so you can't have multiple simultaneous downloads by implementing a download queue:
class DownloadQueue extends Array {
constructor(...args) {
super(...args);
}
push(item) {
const len = super.push(item);
if (this.length === 1) {
this.download(item);
}
return len;
}
shift() {
const item = super.shift();
if (this.length > 0) {
this.download(this[0]);
}
return item;
}
download(item) {
item.options.onCompleted = () => {
this.shift();
};
download(item.win, item.url, item.options);
}
}
And then your 'download'
listener becomes:
const downloadQueue = new DownloadQueue();
ipcMain.on('download', async (event, info) => {
info.win = BrowserWindow.getFocusedWindow();
downloadQueue.push(info);
}
from electron-dl.
@itzsaga @sindresorhus guys, do you have any advice on how to fix onProgress
events with simultaneous downloading?
When I try to download 2nd file while 1st file is downloading, it downloads both files but it starts emitting onProgress
events unexpectedly during the downloading.
Code
I modified the module a bit so it accepts other arguments as well, not just the url
:
ipcMain.on('download-file', async (event, { url, directory, hash }) => {
await download(mainWindow, {
url,
directory,
hash,
onProgress(progress) {
event.sender.send('download-file-progress', progress)
}
})
})
Log:
- Started downloading 1st file
blender-2.81.tar.xz
- After 5 seconds started downloading 2nd file
blender-2.81-windows64.msi
I passed hash-1
for the 1st file and hash-2
for the 2nd into the download()
with the file URL just for the log.
Compare the percentages and the hashes, look at how hashses do not correspond correctly to their files after I started downloading 2nd file:
blender-2.81.tar.xz - 0.00% - hash-1
blender-2.81.tar.xz - 1.88% - hash-1
blender-2.81.tar.xz - 3.88% - hash-1
blender-2.81.tar.xz - 5.89% - hash-1
blender-2.81.tar.xz - 8.14% - hash-1
blender-2.81.tar.xz - 10.40% - hash-1
blender-2.81.tar.xz - 11.40% - hash-1
blender-2.81.tar.xz - 13.65% - hash-1
blender-2.81.tar.xz - 15.74% - hash-1
blender-2.81.tar.xz - 17.79% - hash-1
blender-2.81-windows64.msi - 0.00% - hash-1
blender-2.81-windows64.msi - 0.00% - hash-2
blender-2.81-windows64.msi - 0.00% - hash-1
blender-2.81-windows64.msi - 0.00% - hash-2
blender-2.81-windows64.msi - 19.83% - hash-1
blender-2.81-windows64.msi - 0.50% - hash-1
blender-2.81-windows64.msi - 0.50% - hash-2
blender-2.81-windows64.msi - 21.92% - hash-1
blender-2.81-windows64.msi - 1.56% - hash-1
blender-2.81-windows64.msi - 1.56% - hash-2
blender-2.81-windows64.msi - 23.21% - hash-1
blender-2.81-windows64.msi - 2.77% - hash-1
blender-2.81-windows64.msi - 2.77% - hash-2
blender-2.81-windows64.msi - 24.51% - hash-1
blender-2.81-windows64.msi - 4.03% - hash-1
blender-2.81-windows64.msi - 4.03% - hash-2
blender-2.81-windows64.msi - 26.01% - hash-1
blender-2.81-windows64.msi - 5.33% - hash-1
blender-2.81-windows64.msi - 5.33% - hash-2
blender-2.81-windows64.msi - 27.30% - hash-1
blender-2.81-windows64.msi - 6.48% - hash-1
blender-2.81-windows64.msi - 6.48% - hash-2
blender-2.81-windows64.msi - 28.64% - hash-1
...
from electron-dl.
We do it with this code for an array of objects where there is a url
key on each object.
ipcMain.on("download-files", async (event, files) => {
const downloadLocation = app.getPath("userData");
const promises = files.map(file =>
download(mainWindow, file.url, {
saveAs: false,
directory: downloadLocation,
onProgress: progress => {
event.sender.send("download-progress", { progress, file });
}
})
);
await Promise.all(promises);
});
from electron-dl.
having similar issues, downloading multiple files at the same time makes data leak into the wrong item. For example the progress of file 2 switches back and forth on file 1. So if file 1 is on 10% and file 2 on 20%, file 1 will show 10% then 20% then 10% then 20% on and on again
from electron-dl.
We ran into this as well, where we needed to download two sets of files, each with a dynamic number of files. Some files from one set were getting written to the directory of the other. The way we had to get around this was to make everything synchronous. This ended up working for us:
async function downloadFile({ directory, url, filename }): Promise<string> {
return new Promise((resolve) => {
download(mainWindow, url, {
directory,
filename,
saveAs: false,
showBadge: false,
onCompleted: ({ path }) => {
resolve(path);
},
});
});
}
async function downloadFiles(
directory: string,
files: Array<{ url: string; filename: string }>
): Promise<string[]> {
return await files.reduce(
async (result: Promise<Array<string>>, { url, filename }) => {
const awaitedResults = await result;
try {
const downloadedFile = await downloadFile({ directory, url, filename });
return [...awaitedResults, downloadedFile];
} catch (err) {}
},
Promise.resolve([])
);
}
from electron-dl.
Running into this issue as well.
It looks like the options are being set globally and it looks like only one download can exist at a time.
Lets say I have 10 files I am downloading, and calling the download function in a foreach function.
By the end of it I only have 1 file downloaded, which has the contents of the first download in the list but the name of the last item.
I haven't had time to test but it looks like you might have to wait for a download to completely finish before doing another one. Which is not ideal.
from electron-dl.
class DownloadManager {
public window: any = null
public paths: any[] = []
public options: any = {}
constructor (window: any, paths: any[], options: {} = {}) {
this.window = window;
this.paths = paths;
this.options = options
}
download = async (options?: any) => {
for (let item of this.paths) {
const dl: any = await download(this.window, item.url, {
...this.options,
filename: item.name + '.zip',
onProgress: (progress: any) => {
App.window.webContents.send(options?.progressEventName || 'download-progress', { ...progress, key: item.name })
}
})
if (dl.isDone) {
App.window.webContents.send(options?.successEventName || 'download-complete', { key: item.name })
}
}
}
}
from electron-dl.
Can you give some more context to your code? How and where are you calling this from? Whats the download
function thats being awaited there. Missing some key points here.
from electron-dl.
I wrote a library that addresses the multi-download issue and also supplies an id
to the download as well:
https://www.npmjs.com/package/electron-dl-manager
from electron-dl.
Related Issues (20)
- Support relative paths HOT 1
- MULTIPLY BUG with DOWNLOAD (BIGGEST BUG 2021?) HOT 4
- Cannot find n ame 'Completed'. (new in 3.2) HOT 1
- Utilizing session.enableNetworkEmulation with ElectronDL HOT 1
- TypeError upon evaluation of download() arguments HOT 1
- how to use electron latest in electron-dl HOT 10
- Overwrite Option is flase. but, the same file name is specified in the directory, it is overwritten. HOT 2
- Status of tests and remote module HOT 1
- Downloads stuck on MacOS HOT 5
- Cannot read property 'getType' of null at getWindowFromWebContents
- cannot read 'getOwnerBrowserWindow' HOT 1
- Save-as dialog shows two periods before the SQLite file extension in the file type filter
- Property defination are different between index.d.ts and index.js
- Download URL with POST requests. HOT 1
- is there any sample project i can't make
- how can i make progress bar please help HOT 1
- When I change menu in navbar with route, it goes into loop
- how to post a json param
- Self signed certificate download not working.
- Get "Download Error" when using save as dialog and cancel button is pressed HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from electron-dl.