Я был бы очень признателен за понимание этого поведения Apache.
Я общаюсь с PHP из приложения iPhone Objective-C в приложении / JSON. Сжатие Gzip включено на сервере и запрашивается клиентом.
Из моего .htaccess:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/json
Для небольших запросов Apache устанавливает заголовок «Content-Length». Например (эти значения выводятся в Objective-C из заголовка):
Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Length" = 185; <-------------
"Content-Type" = "application/json";
Date = "Wed, 22 Sep 2010 12:20:27 GMT";
"Keep-Alive" = "timeout=3, max=149";
Server = Apache;
Vary = "Accept-Encoding";
"X-Powered-By" = "PHP/5.2.13";
"X-Uncompressed-Content-Length" = 217;
X-Uncompressed-Content-Length - это заголовок, который я добавляю в размер несжатой строки JSON.
Как видите, этот запрос очень маленький (217 байт).
Вот заголовки из большего запроса (282888 байт):
Connection = "Keep-Alive";
"Content-Encoding" = gzip;
"Content-Type" = "application/json";
Date = "Wed, 22 Sep 2010 12:20:29 GMT";
"Keep-Alive" = "timeout=3, max=148";
Server = Apache;
"Transfer-Encoding" = Identity;
Vary = "Accept-Encoding";
"X-Powered-By" = "PHP/5.2.13";
"X-Uncompressed-Content-Length" = 282888;
Обратите внимание, что Content-Length не указан.
Мои вопросы:
- Почему Apache не отправляет Content-Length для большего запроса?
- Означает ли тот факт, что установлено «Contend-Encoding = gzip», что сжатие gzip все еще работает над большим запросом, хотя я не могу проверить разницу в размере?
- Есть ли способ заставить Apache включать фактическую Content-Length для этих больших запросов, чтобы точнее сообщать пользователям об использовании данных?
Это приложение можно использовать на дорогих тарифных планах, поэтому я хочу сообщать пользователю о фактическом использовании, а не об использовании на 30–70% (несколько сотен дополнительных КБ может показаться не таким уж большим, но эти планы могут стоить от 1 доллара). и 10 долларов за МБ!).
Заранее спасибо.
источник
Похоже, что Apache выполняет чанкованное кодирование, это означает, что он может отправлять данные по мере их сжатия, а не ожидать полного ответа. Это довольно стандартная практика, я недостаточно знаком с Apache, чтобы сказать, можно ли его отключить.
источник
ОК, мне удалось решить это. Как верно указывает Мартин Ф., Apache разбивает ответ на части, поэтому размер контента неизвестен. Для многих это желательно (страница загружается быстрее). Это происходит за счет невозможности сообщить о ходе загрузки.
Для тех, кто, как я, действительно хочет сообщить о ходе загрузки, если вы используете Apache или PHP автоматическую поддержку gzip, вы мало что можете сделать. Решение состоит в том, чтобы сделать это вручную. Это проще, чем кажется
Если вы отправляете целые файлы, то это отличный пример в PHP для принудительной установки одного фрагмента (с длиной содержимого): http://www.php.net/manual/en/function.ob-start.php # 94741
Если вы отправляете сгенерированные данные, используйте gzencode для кодирования ваших данных, как в примере выше. Обязательным условием является то, что все ваши выходные данные хранятся в переменной (вы можете использовать ob_start, чтобы помочь этому, если вам нужно буферизовать, а затем получить содержимое буфера).
И вуаля!
Еще одно большое преимущество, если вы сделаете это самостоятельно, вы можете установить уровень сжатия. Это отлично подходит для моего мобильного приложения, так как я могу установить самый высокий уровень сжатия (так что мои пользователи платят меньше за данные!) - тогда как сервер, вероятно, использует только средний уровень сжатия для лучшего компромисса ЦП / размера. Я полагаю, что уровни сжатия - это то, что вы можете изменить, только если вы можете редактировать httpd.conf (который на общем хостинге я не могу).
Поэтому я сохранил директиву DEFLATE .htaccess для всего, кроме ответов на приложение / json, которые я теперь кодирую указанным выше способом.
Еще раз спасибо Martin F, вы дали мне искру, мне нужно было решить это :)
источник
strlen($replyBody)
вместоmb_strlen($replyBody, 'latin1')
. Длина содержимого - это количество байтов (не символов), которое дает вам strlen (). Использование mb_strlen () с типом 'latin1' работает, так как символы latin1 всегда 8-битные, но могут возникнуть проблемы с кодировками, которые производят байты, которые не являются допустимыми символами latin1.