Подтвердить что ты не робот

Запустите несколько загрузок и получите обратную связь, когда окно подсказки загрузки показало

В настоящее время я пишу небольшую программу, которая генерирует html файл и открывает его браузером по умолчанию для запуска нескольких загрузок.
Я не хочу открывать вкладку/окно для каждой загрузки, поэтому создание скрытых фреймов для загрузки было хорошим решением.
Я использую onload в iframe, чтобы узнать, пока не отображаются подсказки загрузки для каждой загрузки. Однако этот подход в Internet Explorer очень ненадежен.

Так что мне интересно, есть ли способ исправить этот или, может быть, лучший подход?
(Без библиотек, пожалуйста.)

Вот мой код html/js:

<!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>
4b9b3361

Ответ 1

Довольно просто вы не можете знать, началась ли загрузка на родном браузере. У каждого браузера разные способы обработки, пользователь может настроить свой браузер, чтобы запросить местоположение, или он просто может автоматически загрузить его в папку Downloads (по умолчанию в большинстве браузеров в настоящее время). Если он запрашивает место, которое он может отменить по ошибке, но ваша установка все равно будет требовать начала загрузки. Таким образом, нет, нет никакого способа достоверно информировать пользователя о том, что они могут закрыть вкладку после запуска/завершения всех загрузок... при условии, что вы используете механизм загрузки собственного браузера.

Путем достижения этого эффекта возможно, сначала загрузив файл с помощью Javascript (требуя, чтобы у вас был доступ к этим файлам, хотлинкинг к файлам сторонних разработчиков, конечно, не вариант). Чтобы увидеть это в действии попробуйте загрузить файл из mega.nz. Я планировал написать, как это сделать вручную, но уже есть хороший (довольно устаревший) ответ, излагающий это.

Если намерение состоит только в том, чтобы убедиться, что загрузка началась, вы можете реализовать триггер на задней панели, чтобы отметить, когда к нему был обращен доступ. В этом простейшем виде это выглядело бы так:

  • Страница download.html запросы file.php?location=[...]&randomHash=1234
  • Как только загружается file.php, он установит флаг в памяти или базу данных, в которой запущен randomHash id 1234.
  • file.php перенаправляет страницу с заголовком 302 в фактическое местоположение файла.
  • download.html периодически проверяет использование Ajax, был ли поднят флаг randomHash=1234. Если да, то он знает, что загрузка началась.

Ответ 2

В действительности, как сообщается, IE не всегда ведет себя хорошо с обработчиком событий onload iframes. Существует открытая активная запись трекера ошибок.

Проблема обсуждается в нескольких местах в Интернете, и наиболее надежным решением является наличие косвенной загрузки с вложенными iframe: iframe загружает HTML файл с iframe, который загружает файл для загрузки, Причина этого в том, что IE, похоже, не похож на iframes, которые указывают на нечто иное, чем на HTML. Поэтому, если у вас есть возможность сделать это в своей программе:

  • Для каждого загружаемого файла сгенерируйте HTML файл с телом, который выглядит следующим образом:

    <iframe src="http://filetodownload.exe" style="display:none"></iframe>
    
  • Сохраните этот файл во временной папке, например. C:\tmp\filetodownload.html

  • В созданном вами "master" HTML файле замените источник iframe на этот промежуточный файл:

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

Это может сделать трюк. Но, следуя традиции IE, это могло или не могло работать в зависимости от случая...

Если это не сработает, некоторые полезные решения:

  • Поместите обработчик onload в функцию и напишите в определении iframe: onload="return theonloadfunction()" (даже если функция ничего не возвращает)
  • Вместо использования атрибута onload присоедините обработчик событий в javascript, например:

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

Обратите внимание, что attachEvent предназначен только для IE. Если вы хотите поддерживать другие браузеры, вам придется его обнаружить и использовать addEventListener для случаев, отличных от IE.

Наконец, вы можете попробовать комбинации двух или более из этих решений:)

Ответ 3

<html>
    <head>
        <meta content = 'text/html;charset=utf-8' http-equiv = 'Content-Type'>
        <meta content = 'utf-8' http-equiv = 'encoding'>

        <script>
            /*
                First, I removed the setInterval(). Since you rely on the onload property we can aswell just check it on each onload.
                Second, I changed your downloadsInfo to an object array.

                Also be aware while testing, that some browsers cache your cancel/block choice and do not reask again for the same url.
                Additionally firefox does not fire on frame downloads.
                Furthermore the alert in your test might not show for overlapping or setting reasons.
            */

            var downloadsInfo = [
                {url: "http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe", Status: "Connecting"},
                {url: "http://download.piriform.com/ccsetup410.exe", Status: "Connecting"}
            ];

            //IE has a problem in sometimes merely firing the onload propery once, which we bypass by dynamically creating them
            //It is also less limited.
            function iframeConnect(){
                for(var i=0, j=downloadsInfo.length; i<j; i++){
                    var tF = document.createElement('iframe');
                    tF.arrayIndex = i; //For convenience
                    tF.style.display = 'none';

                    //Normal load event, working in ie8-11, chrome, safari
                    tF.onload = function(){
                        iframeExecuted(this.arrayIndex);
                    };

                    //Workaround for firefox, opera and some ie9
                    tF.addEventListener('DOMSubtreeModified', function(){
                        iframeExecuted(this.arrayIndex);
                    }, false);

                    document.body.appendChild(tF);
                    tF.src = downloadsInfo[i].url;
                }
            }

            function iframeExecuted(i){
                downloadsInfo[i].Status = 'Executed';

                var tStatus = iframeFinished();
                var tE = document.querySelector('h3');

                if (tStatus.Done) tE.innerHTML = 'Finished'
                else tE.innerHTML = 'Processed ' + tStatus.Processed + ' of ' + tStatus.Started;
            }

            function iframeFinished(){
                for(var i=0, j=downloadsInfo.length; i<j; i++){
                    if (downloadsInfo[i].Status != 'Executed') break;
                }
                //Note that the Processed value is not accurate, yet it solves is testing purpose.
                return {Done: (i == j), Processed: i, Started: j}
            }
        </script>
    </head>

    <body onload = 'iframeConnect()'>
        <h3>Please wait for your downloads to start and do not reload this site.</h3>
    </body>
</html>