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

Лучший способ начать загрузку?

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

Ответ 3

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

Ответ 4

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

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

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

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

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

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

Ответ 5

Ха!

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

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

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

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

Ответ 9

Чтобы подвести итог, у вас есть 2 цели:

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

Чтобы достичь этого, я бы сделал следующее:

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

И все.

Ответ 10

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

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

Подробнее ответьте.

Ответ 11

Вы можете использовать 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...");
       }
    });
});