Лучший способ начать загрузку? - PullRequest
12 голосов
/ 13 сентября 2008

На веб-сайте на основе 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?"

ОБНОВЛЕНИЕ: я отказался от этого подхода. См. Мой ответ ниже по причинам.

Ответы [ 11 ]

16 голосов
/ 13 сентября 2008

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

<meta http-equiv="refresh" content="5;url=/download.php?doc=123.zip"/>
15 голосов
/ 16 сентября 2008

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

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

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

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

5 голосов
/ 13 сентября 2008

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

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, и это приведет к тому, что браузер откроет окно загрузки, не перепутав содержимое текущей страницы.

1 голос
/ 22 сентября 2008

Ха!

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

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

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

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

С наилучшими пожеланиями, Basty

1 голос
/ 15 сентября 2008

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

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

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

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

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

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

0 голосов
/ 17 апреля 2015

Вы можете использовать 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...");
       }
    });
});
0 голосов
/ 08 апреля 2009
<a href="normaldownload.zip" onclick="use_dhtml_or_ajax_to_display_page()">

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

См. Более полный ответ

0 голосов
/ 15 сентября 2008

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

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

Для этого я бы сделал следующее:

Когда ваш пользователь отправляет форму, он получает получившуюся страницу с опциями пожертвования и текстом о том, что его загрузка начнется через 5 секунд. И в разделе заголовка этой страницы вы поместите код META, как сказал Солдарнал:

И это все.

0 голосов
/ 15 сентября 2008

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

0 голосов
/ 13 сентября 2008

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

<iframe src="/download.exe" frameborder="0" height="0" width="0"><a href="/download.exe">Click here to download.</a></iframe>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...