Возможно многие из Вас уже делали это, но лично я столкнулся с рядом трудностей по выискиванию информации и поэтому решил ею поделиться. Сразу хочу отметить, что серверная часть данного процесса будет выполняться на платформе ASP.NET с использованием языка C#.
Несколько месяцев назад у меня был проект для рекламного агентства, в котором необходимо было сделать онлайн форму по расчету стоимости широкоформатной печати + сделать форму отправки заявки менеджеру с выбранными настройками печати. Также нужно было сделать возможность прикрепления макета для печати к заявке.
Проблема заключалась в том, что размер макета мог составлять до 200 мегабайт, и не показывать процесс загрузки изображения на сервер в данном случае имхо было бы просто неуважительно по отношению к клиенту.
Существующие веб-стандарты, к сожалению, не имеют нативной браузерной поддержки отображения статуса загрузки файла, но разработчики, как известно, народ предприимчивый и немного потанцевав с бубном, можно этого эффекта добиться.
Итак, в коде страницы браузера имеем следующее:
Пользователь выбирает файл и нажимает кнопку Submit. Как известно после этого браузер формирует POST запрос на сервер, в теле которого находится выбранный файл.
Тело запроса передается на сервер не сразу, а частями и Ваш код не получит управление до тех пор, пока весь запрос не передастся на сервер.
Чтобы решить эту проблему воспользуемся HttpWorkerRequest. Данный класс начинает «отрабатывать» себя каждый раз при получении данных на сервер.
Переопределив ряд его методов можно «следить» за тем, сколько данных уже поступило на сервер, и вести по ним статистику.
Регистрируем модуль на сервере в файле web.config:
При получении запроса на загрузку файла подменяем оригинальный воркер на свой:
Далее переопределив методы воркера – сможем получить информацию и кол-ве полученных байт.
По умолчанию, сервер ASP.NET «обрубает» все запросы, которые больше 4Мб. Если Вы хотите принимать длинные запросы в файле web.config нужно указать максимальную длину запроса (в кб):
Суть кода состоит в том, чтобы во время отправки файла с заданной периодичностью опрашивать сервер (используя AJAX) и узнавать сколько данных он получил.
Для написания клиентского кода использовался jQuery. Сам прогресс бар взят у jQueryui.
При загрузке формы мы добавляем параметр __UixdId (название свободное) — служит уникальным идентификатором загрузки. Сервер при получении запроса связывает этот идентификатор со статистикой загрузки.
Также в эту форму добавляем невидимый iFrame. И «смотрим» нашей формой в этот фрейм. Нужно для того, чтобы браузер сложил туда ответ от сервера, по окончании загрузки:
Несколько месяцев назад у меня был проект для рекламного агентства, в котором необходимо было сделать онлайн форму по расчету стоимости широкоформатной печати + сделать форму отправки заявки менеджеру с выбранными настройками печати. Также нужно было сделать возможность прикрепления макета для печати к заявке.
Проблема заключалась в том, что размер макета мог составлять до 200 мегабайт, и не показывать процесс загрузки изображения на сервер в данном случае имхо было бы просто неуважительно по отношению к клиенту.
Существующие веб-стандарты, к сожалению, не имеют нативной браузерной поддержки отображения статуса загрузки файла, но разработчики, как известно, народ предприимчивый и немного потанцевав с бубном, можно этого эффекта добиться.
Итак, в коде страницы браузера имеем следующее:
/>
/>
Серверная часть
Пользователь выбирает файл и нажимает кнопку Submit. Как известно после этого браузер формирует POST запрос на сервер, в теле которого находится выбранный файл.
Тело запроса передается на сервер не сразу, а частями и Ваш код не получит управление до тех пор, пока весь запрос не передастся на сервер.
Чтобы решить эту проблему воспользуемся HttpWorkerRequest. Данный класс начинает «отрабатывать» себя каждый раз при получении данных на сервер.
Переопределив ряд его методов можно «следить» за тем, сколько данных уже поступило на сервер, и вести по ним статистику.
Регистрируем модуль на сервере в файле web.config:
/>
При получении запроса на загрузку файла подменяем оригинальный воркер на свой:
void context_BeginRequest(object sender, EventArgs e) {
HttpApplication _app = sender as HttpApplication;
HttpRequest r = _app.Context.Request;
HttpWorkerRequest origWr = _wr.GetValue(r) as HttpWorkerRequest;
string id;
if (UploadProgressUtils.IsUploadStatusRequest(origWr, out id))// если это запрос статистики то выходим
{
return;
}
if (UploadProgressUtils.IsUpload(origWr)) // если запрос содержит загружаемый файл
{
var s = r.RawUrl;
if (string.IsNullOrEmpty(s))
return;
if (!IsUrlWithExtension.IsMatch(s))
return;
HttpUploadWorkerRequest newWr = new HttpUploadWorkerRequest(origWr); // создаем свой воркер
_wr.SetValue(r, newWr); // и подменяем его
}
}
Далее переопределив методы воркера – сможем получить информацию и кол-ве полученных байт.
По умолчанию, сервер ASP.NET «обрубает» все запросы, которые больше 4Мб. Если Вы хотите принимать длинные запросы в файле web.config нужно указать максимальную длину запроса (в кб):
<system.web>
/>
</system.web>
Клиентская часть
Суть кода состоит в том, чтобы во время отправки файла с заданной периодичностью опрашивать сервер (используя AJAX) и узнавать сколько данных он получил.
Для написания клиентского кода использовался jQuery. Сам прогресс бар взят у jQueryui.
При загрузке формы мы добавляем параметр __UixdId (название свободное) — служит уникальным идентификатором загрузки. Сервер при получении запроса связывает этот идентификатор со статистикой загрузки.
var f = $(config.formId);
this.inUx = $("/>").attr({
id: '__UixdId',
value: '0'
});
this.inUx.attr('name', '__UixdId');
this.inUx.prependTo(f)
Также в эту форму добавляем невидимый iFrame. И «смотрим» нашей формой в этот фрейм. Нужно для того, чтобы браузер сложил туда ответ от сервера, по окончании загрузки:
var frame;
//создаем фрейм
try {
frame = document.createElement('
Далее после сабмита формы включаем таймер и начинаем опрашивать сервер:
var cbDate = new Date();
var utx = Date.UTC(cbDate.getYear(), cbDate.getMonth(), cbDate.getDay(), cbDate.getHours(), cbDate.getMinutes(), cbDate.getSeconds(), cbDate.getMilliseconds());
var url = "UploadProgress.ashx?__UixdId=" + scope.inUx.attr("value") + "&boost=" + utx;
$.getJSON(url, callback);
Данные по статистике на сервере формируются в формате JSON. В url запроса мы указываем тот идентификатор, что мы создали при загрузке документа. Параметр boost содержит уникальную строку и нужен для того, чтобы избежать кеширования ответа браузером.
Чем чаще будем опрашивать сервер, тем более плавным будет движение прогресс бара, но вместе с этим это увеличит нагрузку на сервер.
Загруженный файл Вы можете «поймать» в CodeBehind веб-формы.
Готовый пример
Полный исходный код
Будет интересно услышать Ваши мнения и предложения.