Индикатор прогресса/занятости во время ожидания загрузки файла в javascript?
вот ситуация:
В веб-приложении пользователь выбирает некоторые параметры, отправляет форму, а файл PDF динамически генерируется на стороне сервера и предлагается для загрузки.
Проблема:
Генерация файла PDF занимает довольно много времени (до 1 минуты). Некоторые пользователи считают, что ничего не происходит, и продолжайте нажимать кнопку отправки снова и снова, увеличивая нагрузку на сервер и замедляя его еще дальше.
Мне нужно добавить индикатор занятости, в котором будет отображаться анимированное изображение и сообщение типа "Подождите, ваш файл будет сгенерирован", что кажется очень простым.
Но: как скрыть этот индикатор, когда файл готов, и появляется диалоговое окно "загрузка файла"? В противном случае сообщение остается на экране даже после того, как пользователь скачал файл!
Кажется, очень основное требование, но я полностью застрял. Спасибо за любые предложения!
Ответы
Ответ 1
Я должен был сделать это для чего-то, что заняло гораздо больше времени (преобразование видеоформата). Это может показаться вам излишним, но это действительно сработало.
- Извлеките PDF-код из процесса.
- При запуске задания создайте уникальный идентификатор задания и сохраните его в сеансе. Сообщите этому создателю PDF.
- Заставьте его записать на сервер файл статуса (названный как идентификатор задания), чтобы он записывал "0% завершен" и обновляет его каждые несколько секунд (эта часть зависит от того, что вы можете иметь показатель прогресса в своем процессе... Если это не так, это не сработает)
- Используйте JS, чтобы вытащить этот файл. Вы можете отобразить прогресс для пользователя.
- Когда прогресс равен "100% завершен", нажмите их в папку PDF. Это может помочь, если вы назовете это как идентификатор задания. *
* У нас была еще одна загрузка script, которая переименовала ее в красивое имя (на основе исходного видеофайла) с использованием заголовка содержимого, но это действительно зависит от вас!
Изменить: я должен добавить, что страница ожидания была результатом нажатия кнопки submit. Это была новая pageload, но нет причин, по которым вы не могли бы AJAX весь процесс, просто убедитесь, что, как говорили другие, отключить кнопку отправки при первом щелчке, чтобы остановить пользователя, приходящего на него.
Ответ 2
Я согласен с другими респондентами в том, что наилучшим вариантом будет просто отключить кнопку отправки в форме и дать пользователю индикатор занятости; однако для файлов, которые занимают много времени для его создания, имеет смысл иметь более реалистичный индикатор для пользователя, что вещи не просто зависают.
Один из способов, которым вы могли бы реализовать строку состояния или сообщение об ожидающем обновлении, заключается в том, чтобы JavaScript на стороне клиента выполнял первоначальный вызов на сервере и немедленно возвращал сервер сразу после его создания. Затем вы могли бы опросить JavaScript-опрос через каждые n секунд, чтобы узнать, завершен ли файл. Если у вас есть способ определить статус генерации файлов, вы можете дать числовой ответ для процентного соотношения процентных ставок, или вы можете просто ответить назад на сообщение "все еще работающий".
Я считаю, что этот блог на asp.net обсуждает аналогичную настройку.
Ответ 3
У меня есть сообщение в блоге с потенциальным решением этой проблемы:
http://geekswithblogs.net/GruffCode/archive/2010/10/28/detecting-the-file-download-dialog-in-the-browser.aspx
Этот подход предполагает некоторое сотрудничество между клиентским и серверным кодами. Он работает так (полный пример, включая код, можно найти в моем сообщении в блоге, приведенном выше):
- Пользователь нажимает кнопку "отправить", чтобы сгенерировать файл. Прежде чем данные будут отправлены на обрабатываемый сервер, javascript на стороне клиента выполняет три функции:
- Создает значение "токена" и устанавливает скрытое поле в HTML-форме, которая должна быть отправлена. Значение токена не очень важно; достаточно использовать текущую метку даты и времени на втором.
- Сразу после того, как токен установлен, но до того, как разрешить отправку формы, код на стороне клиента помещает сообщение "система занято", чтобы пользователи знали, что что-то происходит, и не позволяют им отправить форму дважды. jQuery BlockUI plugin отлично работает для этой цели.
- Наконец, время настроено на периодический опрос на наличие куки файла с заранее определенным именем, содержащим значение токена, созданное на шаге 1.
- Теперь у вас есть приятная "обложка" на стороне клиента, которая позволяет пользователю узнать, что что-то происходит, и не дать им дважды щелкнуть кнопку, пока запрос может быть обработан на стороне сервера. Перед отправкой завершенного файла обратно клиенту в качестве загрузки установите cookie с заданным именем в ответе HTTP, который содержит значение маркера, которое было отправлено клиентом.
- Когда HTTP-ответ получен клиентом, код таймера, который выполняет опрос для предопределенного имени cookie, содержащего значение токена, найдет его и сможет выполнить следующее:
- Разблокировать пользовательский интерфейс
- Остановить таймер/код опроса.
Обычно я делаю это с 1-секундным интервалом опроса, поэтому большинству пользователей приходится ждать 1 секунду между тем временем, когда диалог загрузки файлов отображается в браузере и время, когда сообщение "занято системой" исчезает.
Этот подход, на мой взгляд, очень быстрый и простой в реализации. Тем не менее, учитывая, что ваше поколение PDF занимает около 1 минуты, я думаю, что вы приближаетесь к точке, где принятие этой обработки "вне диапазона" и реализация чего-то похожего на то, что было объяснено в принятом ответе, может быть предпочтительнее.
Ответ 4
Вы можете асинхронно опросить сервер (например, с помощью AJAX), чтобы проверить, завершено ли создание этого файла PDF.
В зависимости от этого результата или тайм-аута повторно включите эту кнопку и/или остановите анимацию.
Ответ 5
Я бы поместил это или что-то вроде этого в событие onSubmit. Блок Busy может быть просто div с анимацией ajax load в фоновом режиме. (Я предлагаю анимированный gif по сравнению с анимацией Javascript.) После того, как результат будет возвращен, пользователь увидит PDF после их минутного ожидания. Вы даже можете использовать таймер для уменьшения оценки (например, 60 секунд) и дать пользователю некоторое представление о том, сколько времени может потребоваться.
document.getElementById('busy').style.display = 'block';
document.getElementById('submit').disabled = 'disabled';
Блок занятости:
<div id="busy">
<p>Your PDF is being generated, please wait.</p>
</div>
И общий CSS...
#busy { display: none; background: url(/images/spinner.gif) no-repeat top left; padding-left: 24px; }
Ответ 6
Спасибо всем за предложения.
Тем временем я попробовал еще один подход:
a) В "onclick" отключите кнопку отправки и покажите индикатор занятости.
b) На стороне сервера, когда файл сгенерирован, не выводите его пользователю, а сохраняйте его в файловой системе. Затем отправьте перенаправление на ту же страницу, но с атрибутом "& downloadready = true"
c) При загрузке страницы, если атрибут "downloadready" равен true, инициируйте загрузку файла.
Он работает, но имеет один недостаток: в IE он показал предупреждение "Чтобы защитить вашу безопасность, IE заблокировал загрузку файла bla bla bla", что, по-моему, было бы очень неприятно для пользователей.
Итак, попробуйте использовать метод опроса AJAX.
Ответ 7
Не полный ответ на ваш вопрос, но вы можете отключить кнопку отправки, когда пользователь сделал первый щелчок.
Это позаботится о том, чтобы "пользователь продолжал нажимать, тем самым замедляя работу сервера еще больше".