Вопрос

На веб-сайте на основе PHP я хочу отправить пользователям пакет загрузки после того, как они заполнили короткую форму.Загрузка, инициируемая сайтом, должна быть похожа на такие сайты, как download.com, где говорится: «Ваша загрузка начнется через мгновение».

Пара возможные подходы Я знаю о совместимости браузеров (на основе быстрого теста):

1) Сделайте window.open указывая на новый файл.

- FireFox 3 blocks this.  
 - IE6 blocks this.  
 - IE7 blocks this.

2) Создайте iframe, указывающий на новый файл.

- FireFox 3 seems to think this is OK. (Maybe it's because I already accepted it once?)  
 - IE6 blocks this.  
 - IE7 blocks this.

How can I do this so that at least these three browsers will not object? 

Бонус:существует ли метод, который не требует условных операторов браузера?

(Я считаю, что download.com условно использует оба метода, но я не могу заставить работать ни один из них.)

Ответы и разъяснения:

Q: "Why not point the current window to the file?"  
A: That might work, but in this particular case, I want to show them some other content while their download starts - for example, "would you like to donate to this project?"

ОБНОВЛЯТЬ:Я отказался от этого подхода.Причины смотрите в моем ответе ниже.

Это было полезно?

Решение

Вы также можете выполнить метаобновление, которое поддерживается большинством браузеров.Download.com помещает один из них в тег noscript.

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>

Другие советы

Обновлять:Я решил отказаться от этого подхода и вместо этого просто предоставить пользователю ссылку на реальный файл.Мои рассуждения таковы:

Мои первоначальные попытки загрузки, инициированной сервером, были заблокированы браузером.Это заставило меня задуматься:«Браузер прав.Как это знаете, что это законная загрузка?Это должен заблокировать загрузку, которая явно не инициирована пользователем».

Любой метод, который я могу использовать для загрузки, инициируемой сервером, может также может использоваться кем-то, кто хочет отправить вредоносное ПО.Следовательно, загрузка должна происходить только тогда, когда пользователь специально запрашивает файл, щелкнув ссылку на него.

Вы можете не согласиться, и если вы все же хотите начать загрузку, надеюсь, эта тема поможет вам это сделать.

Обычно у меня есть PHP-скрипт, который выводит файл непосредственно в браузер с соответствующим типом контента.

if(file_exists($filename)) {
    header("Pragma:  public");
    header("Expires:  0");
    header("Cache-Control:  must-revalidate, pre-check=0");
    header("Cache-Control:  private", false);
    header("Content-Type:  " . $content-type);
    header("Content-Disposition:  attachment; filename=\"" . basename($filename) . "\";" );
    header("Content-Transfer-Encoding:  binary");
    header("Content-Length:  " . filesize($filename));

    readfile("$filename");
}else{
    print "ERROR:  the file " . basename($filename) . " could not be downloaded because it did not exist.";
}

Единственным недостатком является то, что, поскольку при этом устанавливается HTTP-заголовок, он вызывается до того, как вы получите какой-либо другой вывод.

Но вы можете иметь ссылку на страницу загрузки PHP, и это заставит браузер открыть окно загрузки, не испортив содержимое текущей страницы.

Одна загвоздка заключается в том, что вы можете столкнуться с проблемами в IE (в частности, версии 6), если заголовки настроены «неправильно».

Убедитесь, что вы установили правильный тип контента, но также рассмотрите возможность установки параметров кэша для IE (по крайней мере) на позволять кэширование.Если файл один, пользователь может открыть его, а не сохранить (например.документ MS Word) ранние версии IE должны кэшировать файл, поскольку они передают запрос «открытия» соответствующему приложению, указывая на файл, который был загружен в кеш.

Существует также связанная с этим проблема: если кеш пользователя IE6 заполнен, он не сможет должным образом сохранить файл (поэтому, когда соответствующее приложение не сможет его открыть, оно будет жаловаться, что файл поврежден.

Вы также можете отключить любые действия gzip при загрузке (для IE).

У IE6/IE7 есть проблемы с большими загрузками (например.4.x Gigs...) маловероятный сценарий, поскольку в IE даже нет менеджера загрузок, но об этом следует знать.

Наконец, IE6 иногда не очень хорошо справляется с загрузкой, если она была инициирована из вложенного iframe.Я не совсем уверен, что вызывает проблему, но считаю, что с IE6 легче избежать этого сценария.

Эй!

@Натан:Я решил сделать именно так:Пусть мой "getfile.php" загрузит все необходимое, а затем выполнит

header("Location: ./$path/$filename");

чтобы позволить самому браузеру делать с файлом все, что он считает правильным.У меня это даже отлично работает в Opera.

Но это будет проблемой в средах, где прямой доступ к файлам не разрешен, в этом случае вам придется искать другой путь!(Слава Discordia, мои файлы являются общедоступными PDF-файлами!)

С уважением, Басти.

Как насчет изменения местоположения, чтобы оно указывало на новый файл?(например.изменив window.location)

Я всегда просто создавал iframe, указывающий на файл.

<iframe src="/download.exe" frameborder="0" height="0" width="0"><a href="/download.exe">Click here to download.</a></iframe>

По поводу не указания текущего окна на загрузку.По моему опыту, вы все равно можете показать свою страницу «пожалуйста, пожертвуйте», поскольку загрузки (при условии, что они отправляют правильные заголовки) фактически не обновляют окно браузера.Я делаю это для экспорта CSV на одном из моих сайтов, и, что касается пользователя, у него просто появляется окно безопасного файла.Поэтому я бы порекомендовал простой мета-редирект, как показал Soldarnal.

Подводя итог, у вас есть 2 цели:

  1. начать процесс загрузки
  2. показать пользователю страницу с опциями пожертвования

Для достижения этой цели я бы сделал следующее:

Когда ваш пользователь отправляет форму, он получает результирующую страницу с опциями пожертвования и текстом о том, что его загрузка начнется через 5 секунд.И в заголовке этой страницы вы помещаете МЕТА-код, как сказал Солдарнал:<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip>

И это все.

<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()">

Текущая страница не затрагивается, если загрузка сохранена.Просто убедитесь, что загрузка не открывается в том же окне (правильный тип MIME или Content-Disposition) и вы сможете показать что угодно.

Посмотреть более полный ответ

Вы можете использовать Javascript/jQuery для начала загрузки.Вот пример: вы можете избавиться от запроса Ajax и просто использовать блок setTimeout().

$("btnDownloadCSV").on('click', function() {
    $.ajax({
        url: "php_backend/get_download_url",
        type: 'post',
        contentType: "application/x-www-form-urlencoded",
        data: {somedata: "somedata"},
        success: function(data) {
            // If iFrame already exists, remove it.
            if($("[id^='iframeTempCSV_"]).length) { 
                $("[id^='iframeTempCSV_"]).remove();
            }
            setTimeout(function() {
                //  If I'm creating an iframe with the same id, it will permit download only the first time.
                // So randHashId appended to ID to trick the browser.
                var randHashId = Math.random().toString(36).substr(2);
                // Create a fresh iFrame for auto-downloading CSV
                $('<iframe id="iframeTempCSV_'+randHashId+'" style="display:none;" src="'+data.filepath+'"></iframe>').appendTo('body');
            }, 1000);
        },
        error: function(xhr, textStatus, errorThrown) {
           console.error("Error downloading...");
       }
    });
});
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top