J'apprécierais vraiment de l'aide pour comprendre ce comportement Apache.
Je communique avec PHP depuis une application iPhone Objective-C dans application / json. La compression Gzip est activée sur le serveur et demandée par le client.
De mon .htaccess:
AddOutputFilterByType DEFLATE text/html text/plain text/xml application/x-httpd-php application/json
Pour les petites demandes, Apache définit l'en-tête «Content-Length». Par exemple (ces valeurs sont sorties dans Objective-C à partir de l'en-tête):
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 est un en-tête que j'ajoute défini à la taille de la chaîne JSON non compressée.
Comme vous pouvez le voir, cette demande est très petite (217 octets).
Voici les en-têtes d'une demande plus importante (282888 octets):
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;
Notez que Content-Length n'est pas indiqué.
Mes questions:
- Pourquoi Apache n'envoie-t-il pas la longueur du contenu pour la plus grande demande?
- Le fait que «Contend-Encoding = gzip» soit défini signifie-t-il que la compression gzip fonctionne toujours sur la plus grande demande, même si je ne peux pas vérifier la différence de taille?
- Existe-t-il un moyen d'obtenir qu'Apache inclue la longueur de contenu réelle pour ces demandes plus importantes afin de rapporter plus précisément l'utilisation des données aux utilisateurs?
Cette application peut être utilisée sur des plans de données qui sont chers, d'où mon désir de signaler l'utilisation réelle à l'utilisateur, pas une utilisation gonflée de 30 à 70% (quelques centaines de Ko supplémentaires peuvent ne pas sembler beaucoup - mais ces plans peuvent coûter entre 1 $ et 10 $ par Mo!).
Merci d'avance.
la source
On dirait qu'Apache fait un codage en morceaux, cela signifie qu'il peut envoyer les données pendant qu'il est compressé au lieu d'attendre que la réponse complète soit compressée. C'est une pratique assez standard, je ne connais pas suffisamment Apache pour dire s'il peut être désactivé, cependant.
la source
OK, j'ai réussi à résoudre ce problème. Comme Martin F le fait remarquer à juste titre, Apache segmente la réponse de sorte que la taille du contenu n'est pas connue. Pour de nombreuses personnes, cela est souhaitable (la page se charge plus rapidement). Cela a pour conséquence de ne pas pouvoir signaler la progression du téléchargement.
Pour ceux comme moi qui veulent vraiment signaler la progression du téléchargement, si vous utilisez Apache ou le support gzip automatique de PHP, vous ne pouvez pas faire grand-chose. La solution est de le faire manuellement. C'est plus simple qu'il n'y paraît:
Si vous envoyez des fichiers entiers, alors c'est un excellent exemple en PHP pour forcer un seul morceau (avec la Content-Length): http://www.php.net/manual/en/function.ob-start.php # 94741
Si vous envoyez des données générées, utilisez gzencode pour encoder vos données, comme dans l'exemple ci-dessus. Une condition préalable est que toutes vos données de sortie soient stockées dans une variable (vous pouvez utiliser ob_start pour vous aider si vous avez besoin de tamponner, puis d'obtenir le contenu du tampon).
Et le tour est joué!
Un autre grand avantage de le faire vous-même est que vous pouvez définir le niveau de compression. C'est génial pour mon application mobile, car je peux définir le niveau de compression le plus élevé (donc mes utilisateurs paient moins pour les données!) - tandis que le serveur n'utilise probablement qu'un niveau de compression moyen pour un meilleur compromis CPU / taille. Les niveaux de compression sont quelque chose que je crois que vous ne pouvez changer que si vous pouvez modifier le httpd.conf (que sur l'hébergement partagé, je ne peux pas).
J'ai donc conservé ma directive DEFLATE .htaccess pour tout sauf mes réponses application / json que j'encode maintenant de la manière ci-dessus.
Merci encore Martin F, vous m'avez donné l'étincelle dont j'avais besoin pour résoudre ce problème :)
la source
strlen($replyBody)
au lieu demb_strlen($replyBody, 'latin1')
. La longueur du contenu est juste le nombre d'octets (pas de caractères), ce que strlen () vous donne. L'utilisation de mb_strlen () avec le type de travail 'latin1' puisque les caractères latin1 sont toujours à 8 bits, mais cela peut avoir des problèmes avec les encodages qui produisent des octets qui ne sont pas des caractères latin1 valides.