Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Start multiple downloads and get feedback when download prompt window showed

I'm currently writing a little program that generates an html file and opens it with the default browser to start multiple downloads.
I don't want to open a tab/window for every download, so creating hidden iframes for the downloads seemed like a good solution.
I'm using onload on the iframes to find out if the download prompts for each download have shown up yet. This approach seems to be very unreliable in the Internet Explorer though.

So I'm wondering if there is there a way to fix this or maybe a better approach?
(Without libraries please.)

Here is my html/js code:

<!DOCTYPE html>
<!-- saved from url=(0016)http://localhost -->
<html><head>
  <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
  <meta content="utf-8" http-equiv="encoding">
  <title>Downloads</title>
  <script>
    "use strict";
    var downloadsInfo = {
        "http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe":"Status: Connecting",
        "http://download.piriform.com/ccsetup410.exe":"Status: Connecting"
    };
    var i = 0;
    var iv = setInterval(function() {
        i = ++i % 4;
        var j = 0;
        var finished = true;
        for (var key in downloadsInfo) {
            var value = downloadsInfo[key];
            if (value != "Status: Download Started!") {
                value = value+Array(i+1).join(".");
                finished = false;
            }
            document.getElementsByTagName("div")[j].innerHTML = key+"<br/>"+value;
            j = j+1;
        }
        if (finished) {
            alert('Done! You can close this window/tab now.');
            clearInterval(iv);
        }
    }, 800);
  </script>
</head><body>
  <h3>Please wait for your downloads to start and do not reload this site.</h3>
  <div></div> <br/><br/>
  <div></div> <br/><br/>
  <iframe src="http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe" onload="downloadsInfo['http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe'] = 'Status: Download Started!';" style="display:none"></iframe>
  <iframe src="http://download.piriform.com/ccsetup410.exe" onload="downloadsInfo['http://download.piriform.com/ccsetup410.exe'] = 'Status: Download Started!';" style="display:none"></iframe>
</body></html>
like image 889
Forivin Avatar asked May 25 '15 11:05

Forivin


People also ask

How do I Turn on automatic downloads in Windows 10?

Scroll down the list of settings until you see the “Automatic Downloads” option. Click on it. By default, the feature is set to ask permission when a site tries to download files in succession.

How do I stop a website from trying to download multiple files?

However, for security reasons, Google Chrome now prompts you when a website tries to download multiple files. Fire up Chrome, click the menu icon, and then click “Settings.” Alternatively, you can type chrome://settings/ into the Omnibox to go directly there.

Is it possible to block all download attempts at once?

However, if you want to block all attempts regardless of the site, or maybe you would rather blacklist a specific website, here’s how. Sometimes when you download a file in a browser, the website will try to download another file immediately after the first finishes.

Should I disable automatic successive file downloads?

Globally disabling automatic successive file downloads isn’t recommended, as it will block every attempt regardless of where it comes from, even legitimate ones that you might expect to download automatically.


2 Answers

Quite simply you can't know whether a native browser download started. Every browser has different ways this is handled, the user may set up his browser to prompt the location or he might just let it auto download to the Downloads folder (the default in most browsers nowadays). If he's prompting for a location he might cancel by mistake, yet your setup would still claim the download started. So, no, there is no way whatsoever to reliably inform the user that they can close a tab once all downloads are started/finished... provided that you use the native browser download mechanism.

The way to achieve this effect would be possibly by first downloading the file using Javascript (requiring you to have access to those files, hotlinking to third party files is of course not an option then). To see this in action try downloading a file from mega.nz. I was planning on writing up how to do this by hand, but there is already a nice (quite outdated) answer outlining this.

If the intention is only to ensure that the download has started you could implement a trigger on the back end to note when the file has been accessed. In it's simplest form this would look like:

  1. Page download.html requests file.php?location=[...]&randomHash=1234
  2. Once file.php is actually loaded it will set a flag in memory or the database that randomHash id 1234 has started.
  3. file.php redirects the page with a 302 header to the actual file location.
  4. download.html checks periodically using Ajax whether flag randomHash=1234 has been raised. If so it knows the download has started.
like image 53
David Mulder Avatar answered Oct 03 '22 23:10

David Mulder


Indeed IE is reported to not always behave nicely with the onload event handler of iframes. There is an active bug tracker record opened.

The problem is discussed in a number of places around the web, and what seems to be the most reliable solution is to have an indirect download with nested iframes: the iframe loads a HTML file with an iframe that loads the file to download. The reason for that is that IE does not seem to like iframes that point to something else than HTML. So if you have the possibility to do that in your program:

  1. For each file to download, generate a HTML file with a body that looks like this:

    <iframe src="http://filetodownload.exe" style="display:none"></iframe>
    
  2. Store this file in a temporary folder, e.g. C:\tmp\filetodownload.html

  3. In your "master" generated HTML file, replace the iframe source with this intermediate file:

    <iframe src="C:\tmp\filetodownload.html" 
            onload="downloadsInfo['http://filetodownload.exe']='Status: Download Started!';" 
            style="display:none"></iframe>
    

That may do the trick. But following IE's tradition, this could or could not work depending on the case...

If it does not work, some solutions that have proved useful include:

  • Put the onload handler in a function, and write in the definition of the iframe: onload="return theonloadfunction()" (even if the function does not return anything)
  • Instead of using the onload attribute, attach the event handler in javascript, like so:

    iframe = document.getElementById("theiframeid")
    iframe.attachEvent("onload", theonloadfunction);`
    

Note that attachEvent is for IE only. If you want to support other browsers you will have to detect it and use addEventListener for the non-IE cases.

Finally, you may try combinations of two or more of these solutions :)

like image 42
Djizeus Avatar answered Oct 03 '22 22:10

Djizeus