Я видел кучу подобных вопросов, о которых вы спрашивали раньше, но я не нашел тот, который точно описывает мою текущую проблему, поэтому:
У меня есть страница, которая загружает большой (от 0,5 до 10 МБ) JSON-документ через AJAX, чтобы клиентский код мог его обработать. Как только файл загружен, у меня нет никаких проблем, которые я не ожидаю. Однако загрузка занимает много времени, поэтому я попытался использовать XHR Progress API, чтобы отобразить индикатор выполнения, чтобы указать пользователю, что Документ загружается. Это хорошо работает.
Затем, чтобы ускорить работу, я попытался сжать вывод на серверной стороне через gzip и сфотографировать. Это тоже сработало, но с огромным успехом мой индикатор прогресса перестает работать.
Я некоторое время изучал эту проблему и обнаружил, что если надлежащий заголовок Content-Length
не отправляется с запрошенным ресурсом AJAX, обработчик события onProgress
не может функционировать должным образом, поскольку он не знает, как далеко в процессе загрузки. Когда это произойдет, свойство lengthComputable
устанавливается на false
объекта события.
Это имело смысл, поэтому я попытался настроить заголовок явно как с несжатой, так и с сжатой длиной вывода. Я могу проверить, что отправляется заголовок, и я могу проверить, что мой браузер знает, как распаковывать содержимое. Но обработчик onProgress
все еще сообщает lengthComputable = false
.
Итак, мой вопрос: есть способ gzipped/deflated content с API AJAX Progress API? И если да, то что я делаю неправильно прямо сейчас?
Так отображается ресурс на панели "Сеть Chrome", показывая, что сжатие работает:
Это соответствующие заголовки запрос, показывающие, что запрос AJAX и что Accept-Encoding
установлен правильно:
GET /dashboard/reports/ajax/load HTTP/1.1
Connection: keep-alive
Cache-Control: no-cache
Pragma: no-cache
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.99 Safari/537.22
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Это соответствующие заголовки ответ, показывающие, что параметры Content-Length
и Content-Type
установлены правильно:
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Encoding: deflate
Content-Type: application/json
Date: Tue, 26 Feb 2013 18:59:07 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
P3P: CP="CAO PSA OUR"
Pragma: no-cache
Server: Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8g PHP/5.4.7
X-Powered-By: PHP/5.4.7
Content-Length: 223879
Connection: keep-alive
Для чего это стоит, я пробовал это как на стандартном (http), так и на защищенном (https) соединении без каких-либо различий: контент загружается в браузере, но не обрабатывается API-интерфейсом Progress.
Per предложение Adam, я попытался переключить серверную сторону на кодировку gzip без каких-либо успехов или изменений. Вот соответствующие заголовки ответов:
HTTP/1.1 200 OK
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Encoding: gzip
Content-Type: application/json
Date: Mon, 04 Mar 2013 22:33:19 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
P3P: CP="CAO PSA OUR"
Pragma: no-cache
Server: Apache/2.2.8 (Unix) mod_ssl/2.2.8 OpenSSL/0.9.8g PHP/5.4.7
X-Powered-By: PHP/5.4.7
Content-Length: 28250
Connection: keep-alive
Просто повторить: содержимое загружается и декодируется должным образом, это просто API прогресса, с которым у меня возникают проблемы.
Per запрос Бертран, здесь запрос:
$.ajax({
url: '<url snipped>',
data: {},
success: onDone,
dataType: 'json',
cache: true,
progress: onProgress || function(){}
});
И вот обработчик событий onProgress
, который я использую (это не слишком сумасшедший):
function(jqXHR, evt)
{
// yes, I know this generates Infinity sometimes
var pct = 100 * evt.position / evt.total;
// just a method that updates some styles and javascript
updateProgress(pct);
});