En-tête Content-Length versus encoding chunked

j'essaie de peser le pour et le contre de la mise en place du Content-Length en-tête HTTP par rapport à l'utilisation d'encodage tronqué pour retourner [possiblement] de gros fichiers à partir de mon serveur. L'un ou l'autre doit être compatible avec les spécifications HTTP 1.1 en utilisant des connexions persistantes. Je vois l'avantage de l' Content-Length header :

  • les boîtes de dialogue de téléchargement peuvent afficher la barre de progression exacte
  • le Client sait à l'avance si le fichier peut / peut ne pas être trop grand pour lui ingérer

l'inconvénient est de devoir calculer la taille avant de retourner l'objet qui n'est pas toujours pratique et pourrait ajouter à l'utilisation du serveur/base de données. L'inconvénient de chunked encoding est le petit overhead de l'ajout de la taille de chunk avant chaque chunk et la barre de progression de téléchargement. Toutes les pensées? D'autres considérations HTTP pour les deux méthodes auxquelles je n'ai peut-être pas pensé?

29
demandé sur DisgruntledGoat 2010-03-10 20:58:11

3 réponses

utilisez Content-Length, definitely. L'utilisation du serveur à partir de ce sera quasiment inexistant et les avantages pour vos utilisateurs seront grandes.

pour le contenu dynamique, il est aussi assez simple d'ajouter le support de réponse compressée (gzip). Cela nécessite un tampon de sortie, qui à son tour vous donne la longueur du contenu. (pas pratique avec les téléchargements de fichiers ou le contenu déjà compressé (son,images)).

pensez également l'ajout du support pour partielle contenu/byte-portée-c'est-à-dire la capacité de redémarrer les téléchargements. Voir ici pour un byte-range exemple (l'exemple est en PHP, mais est applicable dans n'importe quelle langue). Vous avez besoin de la longueur du contenu lorsque vous servez du contenu partiel.

bien sûr, ce ne sont pas des balles en argent: pour les médias en streaming, il est inutile d'utiliser la mise en mémoire tampon de sortie ou la taille de réponse; pour les gros fichiers, la mise en mémoire tampon de sortie n'a pas de sens, mais le contenu-longueur et la portion byte fait beaucoup de sens (redémarrer un téléchargement raté est possible).

personnellement, je sers Content-Length dès que je le connais; pour le téléchargement de fichiers, vérifier la taille du fichier est insignifiant en termes de ressources. Résultat: l'utilisateur dispose d'une barre de progression définie (et les pages dynamiques téléchargent plus rapidement grâce à gzip).

28
répondu Piskvor 2010-03-10 18:37:05

si la longueur du contenu est connue à l'avance, alors je préférerais certainement qu'elle soit au-dessus de l'envoi de morceaux. S'il y a des moyens de fichiers statiques au système de fichiers Disque local ou dans une base de données, alors n'importe quel langage de programmation auto-respecté et RDBMS fournit des moyens d'obtenir la longueur du contenu à l'avance. Vous devriez faire usage de il.

en revanche, si la longueur du contenu est vraiment imprévisible à l'avance (par exemple, lorsque votre intention est de compresser plusieurs fichiers ensemble et l'envoyer comme une), ensuite, l'envoyer en morceaux peut être plus rapide que de le mettre en mémoire tampon dans la mémoire du serveur ou d'écrire au système de fichiers Disque local en premier. Mais cela affecte en effet l'expérience de l'utilisateur négativement parce que la progression du téléchargement est inconnue. L'impatient peut alors interrompre le téléchargement et avancer.

un Autre avantage de connaître la longueur du contenu à l'avance est la possibilité de reprendre les téléchargements. Je vois dans l'historique de votre post que votre langage de programmation principal est Java; vous pouvez trouver ici une article avec des informations de fond plus techniques et un exemple de Servlet Java qui fait cela.

10
répondu BalusC 2010-03-10 18:50:49

Content-Length

Content-Length header détermine la longueur du byte du corps de la requête/réponse. Si vous négligez de spécifier le Content-Length en-tête, les serveurs HTTP ajouteront implicitement un Transfer-Encoding: chunked en-tête. Content-Length et Transfer-Encoding l'en-tête ne doit pas être utilisé en même temps. Le destinataire n'a aucune idée de la longueur du corps et ne peut pas estimer le temps de téléchargement. Si vous ajoutez un Content-Length en-tête, assurez - vous qu'il correspond au corps entier en octets, s'il est incorrect, le comportement des récepteurs n'est pas défini.

Content-Length en-tête ne permettra pas la diffusion en continu, mais il est utile pour les grands fichiers binaires, où vous voulez prendre en charge une portion de contenu. Il s'agit essentiellement de téléchargements réutilisables, de téléchargements interrompus, de téléchargements partiels et de téléchargements à Homes multiples. Cela nécessite l'utilisation d'un en-tête supplémentaire appelé Range. Cette technique s'appelle Byte servir.

Transfer-Encoding

Transfer-Encoding: chunked est ce qui permet la diffusion en continu à l'intérieur d'une seule requête ou réponse. Cela signifie que les données sont transmises de manière tronquée et n'ont pas d'incidence sur la représentation du contenu.

officiellement, un client HTTP est destiné à envoyer une requête avec un TE champ d'en-tête qui spécifie les types d'encodages de transfert que le client est prêt à accepter. Ce n'est pas toujours envoyé, cependant, la plupart des serveurs supposent que les clients peuvent traiter chunked encodages.

chunked l'encodage de transfert fait un meilleur usage des connexions TCP persistantes, ce que HTTP 1.1 suppose être vrai par défaut.

Content-Encoding

il est également possible de compresser des données tronquées ou non. Cela se fait pratiquement via le Content-Encoding en-tête.

notez que le Content-Length est égal à la longueur du corps, après la Content-Encoding. Cela signifie que si vous avez gzippé votre réponse, alors le calcul de la longueur se produit après la compression. Vous devrez être en mesure de charger l'ensemble du corps en mémoire si vous voulez calculer la longueur (sauf si vous avez cette information ailleurs).

lors de la diffusion en continu en utilisant un encodage tronqué, l'algorithme de compression doit également prendre en charge le traitement en ligne. Heureusement, gzip supporte la compression de flux. Je crois que le contenu est d'abord comprimé, puis découpé en morceaux. De cette façon, les morceaux sont reçus, puis décompressé pour acquérir le contenu réel. Si c'était le contraire, vous obtiendriez le flux comprimé, et la décompression nous donnerait des morceaux. Qui n'a pas de sens.

une réponse de flux compressé typique peut avoir ces en-têtes:

Content-Type: text/html
Content-Encoding: gzip
Transfer-Encoding: chunked

Sémantiquement l'utilisation de Content-Encoding indique un schéma d'encodage "de bout en bout", ce qui signifie que seul le client final ou le serveur final est censé décoder le contenu. Les mandataires du milieu ne sont pas censés décoder le contenu.

si vous voulez permettre aux mandataires du milieu de décoder le contenu, l'en-tête à utiliser est en fait le Transfer-Encoding en-tête. Si la requête HTTP possède un TE: gzip chunked en-tête, puis il est légal de répondre à Transfer-Encoding: gzip chunked.

cependant ceci est très rarement soutenu. Vous devez utiliser uniquement Content-Encoding pour votre compression en ce moment.

Chunked vs Store & Forward

2
répondu Dhairya Lakhera 2017-12-11 12:27:42