Riding the bandwagon internet


l'Envoi de grandes pages de HTML n'est plus un problème maintenant que nous pouvons vous envoyer les pages comprimé !

Après deux semaines non-stop de la programmation, votre application web est prêt et testé. Tout est OK et les sourires sur vos clients est confronté à vous rappeler dans une drôle de façon de 'Jaws'. Sauf pour une chose. Quelqu'un dans le dos timidement demande si quelque chose pouvait être fait pour accélérer la page de résultat de recherche qui contient beaucoup de texte. À cet instant, vous savez que vous devriez avoir apporté une copie complète de l'application avec vous au lieu de démonstration au-dessus de votre 33.6 ko ligne modem au travail.

Mais tout n'est pas perdu. Il y a des moyens de réduire la quantité de données que vous devez envoyer au client, et je ne parle pas de la transmission de moins d'informations, mais plutôt sur l'envoi de données compressées. Semble intéressant? Lire la suite et en savoir plus.

Frivole assumptionsSince cet article décrit les fonctionnalités et les techniques qui seront ajouter à la complexité d'une application web, il est supposé que vous savez déjà comment créer une application web, plus précisément une dll ISAPI, ainsi que la façon dont une telle application fonctionne. En tant que tel, je vais sauter sur quelques détails, mais rassurez - vous, je vais vous présenter toutes les options et le code nécessaire spécifiquement pour les techniques que nous mettons en œuvre ici.

Avec cela à l'esprit, nous allons aller serrer quelques plus de jus de vos good ol' Internet en ligne.

Comment est la magie fait?Comment est-ce possible me direz-vous? Vous avez probablement à un moment ou à un autre de téléchargement un fichier compressé seulement pour trouver que votre navigateur en quelque sorte interprété les données sous la forme d'une page web ou un texte et affiche sur votre écran dans toute sa gloire. Pas une belle image pour dire le moins. Si vous étiez à compresser les données avant de les envoyer au client, ne serait-ce pas un aspect tout aussi étrange? Pas tout à fait, seulement assurez-vous que le client sait qu'il doit traiter différemment.

Le secret est caché à l'intérieur les données que le client envoie au serveur et à l'intérieur des données, le serveur répond avec. Il est appelé Codage de Contenu. En bref, vous pouvez coder les données de votre application renvoie au client, et la seule précaution que vous devez prendre est de s'assurer que le client sait comment gérer les données dans l'encodage au format de votre choix. Ce tour est simple depuis que le client vous dit que les formats qu'il peut gérer quand il envoie la demande au serveur.

Donc ce que tout se résume à de la, est que vous devez prendre les mesures suivantes si vous souhaitez encoder les données renvoyées au client:

  1. Vérifier si le client peut gérer le type de codage que vous souhaitez utiliser
  2. Encoder les données dans le format choisi
  3. Retour à la nouvellement données codées et dire au client quel format que vous avez codé en

Quel format dois-je utiliser?Nous nous intéressons en compressant les données que nous le retourner au client. Il y a un type de codage spécifiquement pour cet usage, et son nom est 'dégonfler'. L'algorithme de compression utilisé dans le dégonfler type de codage correspond à l'algorithme de la bibliothèque de compression zLib met en œuvre. Vous pouvez lire plus au sujet de cette bibliothèque ici: http://www.cdrom.com/pub/infozip/zlib ou consultez la rfc décrivant l'algorithme et c'est un format binaire ici: http://www.funet.fi/pub/doc/rfc/rfc1950.txt.

Bien que vous pourriez penser que vous avez déjà les fichiers nécessaires pour l'utilisation de la bibliothèque de compression zLib - vous ne l'avez pas! Au moins, pas exactement. Même si le Delphi CD d'installation livré avec une copie de la bibliothèque de compression zLib dans le formulaire de pré-compilé les fichiers objets et certains d'importer des fichiers, ils se cachent les détails, nous devons utiliser. Plus sur cela plus tard, mais pour l'instant laissez?s il suffit de dire que nous avons besoin d'une meilleure interface pour la bibliothèque et pour cela j'ai choisi de vous livrer ma propre zLib unitaires des importations et un lien de téléchargement du fichier dll: http://www.winimage.com/zLibDll/.

Comme pour le 'deflate' encodage de type Microsoft Internet Explorer s'affiche à gérer et encore, seulement les versions ultérieures (version 4 et gère pour vous, rien en dessous qui n'est pas sûr). Ce n'est pas un gros problème, toutefois, étant donné que les autres navigateurs comme Netscape, ne dis pas qu'ils peuvent gérer la compression type de codage. Dans ce cas, notre application web ne serait tout simplement pas de retour avec les données compressées. La seule différence peut-être un peu plus de temps à télécharger les données au client. Ce n'est pas pire que ce que nous avons aujourd'hui, donc je pense qu'on peut vivre avec ça.

Ok, j'ai récupéré les fichiers, maintenant ce qui?Maintenant, il est temps de descendre les détails sanglants. Nous allons prendre un bon de commencer par créer un nouveau projet ISAPI dans Delphi 5 et voir où cela nous mène. Vous devez ajouter le fichier téléchargé unitaires à l'importation de ce projet. La dll que vous venez de télécharger peut être mis soit dans le C:\Winnt\System32 répertoire (ou de votre répertoire) ou dans le même répertoire que votre application web.

Après la création du nouveau projet, nous allons ajouter un peu d'action, littéralement. Ajouter une action pour le module web et de créer un gestionnaire d'événements vide. Faire de l'action l'action par défaut, car c'est juste une démo de l'application pour essayer notre nouveau mode de renvoi de données.

Nous avons maintenant un vide d'action gestionnaire d'événements pour laisser?s ajouter un peu de code pour elle qui va faire ce dont nous avons besoin. Je vais vous montrer le gestionnaire d'événement complet en premier et ensuite je vais aller dans les détails.

procédure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject Demande: TWebRequest Réponse: TWebResponse var
Manipulé: Boolean)
var
PlaintextStream : TStream
CompressedStream : TStream
démarrer
si ( ClientAcceptsDeflate( Demande ) )
démarrer
// 1. Tout d'abord, créer des cours d'eau temporaires avec les données de retour
PlaintextStream := TStringStream.Créer ('Ce texte est compressé')

// 2. Deuxièmement, créer des cours d'eau temporaires pour nos données compressées
CompressedStream := TMemoryStream.Créer

// 3. Maintenant compresser le flux...
zLibCompressStream( PlaintextStream, CompressedStream )

// ... et le retour
CompressedStream.Position := 0
la Réponse.ContentStream := CompressedStream
sauf
FreeAndNil( CompressedStream )
augmenter
fin // essayez de sauf - éviter les fuites de mémoire
enfin
// 4. Enfin de ranger l'objet temporaire
FreeAndNil( PlaintextStream )
fin // essayez de enfin - détruire en clair un objet de flux
la Réponse.ContentType := 'text/plain'
la Réponse.ContentEncoding := 'deflate'
la Réponse.StatusCode := 200
Manipulé := True
fin// si le client accepte que les données compressées
else begin
la Réponse.Contenu : = 'Non compressé'
la Réponse.ContentType := 'text/plain'
la Réponse.StatusCode := 200
Manipulé := True
fin // si le client n'accepte pas les données compressées
fin // procédure TWebModule1.WebModule1ActionItem1Action

Le principal if ici détermine si oui ou non le client peut gérer la compression de données et les envoie ensuite compressé ou non compressé des données vers le client en conséquence. Les données non compressées sont traitées comme vous l'avez toujours traité les données dans une application web, donc nous n'allons pas en discuter davantage. Au lieu de cela, nous allons nous concentrer sur la si-alors partie de l'if qui gère les données compressées. Vous avez probablement remarqué que nous sommes à l'aide de deux nouvelles procédures/fonctions ici, à savoir ClientAcceptsDeflate et zLibCompressStream. Je vais plus loin dans cet article.

en Supposant que nous avons une procédure qui prend un flux d'entrée, compresse les données de ce volet tient et écrit les données compressées dans un flux de sortie, nous pouvons décrire le code ci-dessus comme ceci:

  1. tout d'Abord créer un cours d'eau temporaire contenant ce que nous voulons retourner au client
  2. Deuxièmement, compresser ces données et de mettre les données compressées à un nouveau flux de données
  3. Ce nouveau courant, la tenue de nos données compressées, il nous suffit de retourner sur le client
  4. Enfin, nous avons rangé nos objets temporaires

Vous pouvez trouver la correspondance des points de cette liste dans le numérotés commentaires ci-dessus gestionnaire d'événement. Il est assez simple de code, et il doit être trop depuis que nous avons caché les détails sanglants dans les deux fonctions, dont nous parlerons ensuite.

Une chose à noter est que, une fois que nous attribuer le ContentStream propriété de l'objet de la Réponse à notre flux de la réponse-objet prend en charge le flux de données. Une fois les données de réponse a été envoyée au client le flux sera libéré pour nous, alors nous devons nous assurer de ne pas accidentellement gratuit nous-mêmes. Dans le cas d'une exception cependant, je fais l'hypothèse que la cession s'est détraqué et ainsi libérer le flux avant la propagation de l'exception plus haut.

Parlez-vous français?Pour déterminer si le client sait comment gérer les données compressées nous devons prendre un regard sur les données qu'il nous envoie en premier lieu. Typique du web demande ressemble à ceci (faux demande, de sorte que les détails peuvent ne pas être 100% correct):

GET /index.html HTTP/1.0
Accept-Types: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla 4.0 (Microsoft Internet Explorer 5.0 (Compatible NT)

Ce qui nous intéresse c'est la ligne qui va de Accept-Encoding: gzip, deflate. Il nous dit quels types d'encodage, le client est en mesure d'accepter, et dans ce cas, il peut accepter des données encodées dans le format gzip ainsi que le dégonfler format. Ce dernier est l'un nous devons, donc, nous allons voir comment faire pour obtenir que la connaissance de l'intérieur de notre application web. La fonction ressemble à ceci:

La fonction que nous avons besoin d'écrire ressemble à ceci:

fonction ClientAcceptsDeflate( const Demande: TWebRequest ): Boolean
var
EncodingTypes : string
démarrer
// reformater liste des types d'encodage de la requête
EncodingTypes := Request.GetFieldByName( 'HTTP_ACCEPT_ENCODING' )
EncodingTypes := Majuscule( StringReplace( EncodingTypes, ',', '/', [ rfReplaceAll ] ) )
EncodingTypes := '/' StringReplace( EncodingTypes, ' ', ', [ rfReplaceAll ] ) '/'

// Retourne le drapeau
Result := ( Pos( '/DÉGONFLAGE/', EncodingTypes ) > 0 )
fin // fonction ClientAcceptsDeflate

bref j'ai reformater les valeurs de gzip, deflate dans /GZIP/DEFLATE/, puis vérifiez si la chaîne de caractères /DÉGONFLAGE/ se trouve en son sein. Si vous êtes intéressé à savoir ce que les autres champs peuvent être trouvés dans la requête, alors je vous suggère de prendre un coup d'oeil à http://msdn.microsoft.com/library/psdk/iisref/isre504l.htm et l'utilisation de la ALL_HTTP variable pour vérifier que les variables le client envoie.

Naturellement, parlons!Après nous avons déterminé que le client peut en effet gérer des données compressées tout ce que nous avons à faire, c'est en fait de produire les données compressées et c'est là que le magie entre.

Comme indiqué précédemment, nous allons utiliser la bibliothèque de compression zLib pour faire de la compression. Le code comprend les étapes suivantes:

  1. mettre en place des tampons pour l'alimentation des données vers le moteur ainsi que d'accepter les données compressées à partir de
  2. Initialiser le moteur de compression
  3. Alimentation des données en texte brut dans le tampon d'entrée du flux d'entrée
  4. Compresser la mémoire tampon d'entrée de la mémoire tampon de sortie
  5. Écrire des données à partir de la mémoire tampon de sortie pour le flux de sortie
  6. Répétez les étapes 3 à 5 jusqu'à ce que plus de données dans le flux d'entrée et de tampons ont été vidés
  7. Fermer le moteur de compression

nous allons creuser dans les détails et voir ce que nous avons à faire face:

procédure zLibCompressStream( const de la Source, de la Destination: TStream )
var
z_s : z_stream
rc : Integer
// 1. Les tampons d'entrée et de sortie
SourceBuffer : array[ 0..BufferSize-1 ] de Byte
DestinationBuffer : array[ 0..BufferSize-1 ] de Byte
démarrer
// 2. Préparer la zLib enregistrement des données
z_init_zstream( z_s )
z_s.next_in := @SourceBuffer
z_s.next_out := @DestinationBuffer
z_s.avail_out := BufferSize

// 2. Initialiser le moteur de compression
deflateInit2( z_s, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY )

// Maintenant compresser le flux

repeat
// 3. Voir si nous sommes arrivés à nourrir plus de données vers le moteur de compression
si ( z_s.avail_in = 0 ) et ( Source.Position < Source.Taille )
démarrer
z_s.next_in := @SourceBuffer
z_s.avail_in := Source.Lire( SourceBuffer, Buffersize )
fin // si les données d'entrée complètement épuisée

// 4. Compresser les données
si ( z_s.avail_in = 0 )
rc := dégonfler( z_s, Z_FINISH )
else
rc := dégonfler( z_s, Z_STREAM_END )

// 5. Vérifier si nous avons obtenu des données compressées pour écrire à destination
si ( z_s.avail_out = 0 ) ou ( rc = Z_STREAM_END )
démarrer
Destination.WriteBuffer( DestinationBuffer, BufferSize - z_s.avail_out )
z_s.avail_out := BufferSize
z_s.next_out := @DestinationBuffer
fin // si obtenu des données disponibles pour l'écriture

// 6. Répétez jusqu'à ce que les tampons épuisé
au ( rc <> Z_OK ) ou ( ( rc = Z_STREAM_END ) et ( z_s.avail_out = BufferSize ) et ( z_s.avail_in = 0 ) )
enfin
// 7. Nettoyer le moteur données
deflateEnd( z_s )
fin // essayez enfin de nettoyer après le moteur
fin // procédure zLibCompressStream

Comme avant, vous pouvez faire correspondre les points de cette liste avec le numéro commentaires ci-dessus. La raison pour laquelle nous ne pouvions pas utiliser la zLib code?s inclus avec Delphi est qu'il cache la deflateInit2 routine et les paramètres nécessaires à l'intérieur de la mise en œuvre de la partie de l'unité ainsi que de ne pas s'exposer à tout le code nécessaire.

afin de produire des données compressées de manière à ce que le navigateur peut gérer, nous avons besoin de compresser les données sans enregistrement d'en-tête. L'enregistrement d'en-tête est un petit enregistrement de l'information qui est écrit au tout début de la compression de données et aide le moteur à décompression savoir la quantité de données qui suit. Nous pouvons choisir de ne pas écrire cet enregistrement d'en-tête en passant une valeur négative pour la wBitSize paramètre à la deflateInit2 procédure. Depuis le dégonfler standard que les navigateurs respectent, ne s'attend pas, ni ne sait comment gérer cette en-tête, nous avons à filtrer. Puisque nous ne pouvions pas appeler deflateInit2 directement avec zLib code fourni avec Delphi, nous avons dû recourir à une complète de dll exemplaire de la bibliothèque de compression.

Le moteur de compression est capable de compresser les données de la mémoire tampon d'entrée et l'écrire dans le tampon de sortie. Lors de la sortie de la mémoire tampon est pleine, notre code de vider cette mémoire tampon et d'écrire les données à la destination, dans notre cas d'un ruisseau. Quand il a réussi à compresser toutes les données de la mémoire tampon d'entrée, notre code doit remplir la mémoire tampon de nouveau avec autant de données que possible. Le moteur de compression prend en charge le reste.

les Tests itAfter de la compilation de votre application web (voir en bas de l'article pour une copie de l'exemple de projet mis en œuvre dans cet article), vous devez idéalement tester avec un navigateur qui gère les données compressées et avec celui qui ne l'est pas. Vous pouvez utiliser Internet Explorer 4 et 5 que l'ancien et Netscape 4.06 que les derniers. Le navigateur qui gère la compression doit afficher le texte 'Ce texte est compressé' et l'autre 'Non compressé' à des fins de vérification.

Moyenne des taux de compression sur la base de texte contenu est d'environ 5-6 fois (de 15 à 20% de la taille originale) de sorte que l'effet doit être clairement visible sur de grandes pages web.

en l'Enveloppant une résurgence, c'est tout. Avec le code et les connaissances contenues dans cet article, vous devriez maintenant être en mesure de traiter les données compressées à partir de votre application web. Même si nous avons créé une dll ISAPI dans cet article, la théorie et le code doit rester la même pour les CGI et NSAPI applications.

j'ai pris la liberté de créer une unité avec les deux fonctions décrites ci-dessus, ainsi qu'une copie de l'exemple produits dans cet article. Vous pouvez télécharger les fichiers à partir de la liste ci-dessous. Si il y a des suggestions ou des choses que vous aimeriez commenter je peux être atteint à [email protected].

les Fichiers à télécharger:

  • zLib dll (à partir du site web d'auteurs)
  • Importer unité pour zLib.dll
  • Exemple de projet (y compris l'unité avec les deux fonctions ainsi que l'importation de l'unité)
  • Uniquement l'appareil avec les deux fonctions que nous avons écrit

Il ya un couple de finition notes de garder à l'esprit:

  • Le moteur de compression ne permet pas de déterminer si les données se prête facilement à la compression ou pas avant qu'il ne commence à mâcher sur elle. Cela signifie qu'il est possible de fournir des données par le biais de ce qui ne peut être compressé et pourrait même augmenter en taille. Pour du texte et des pages web ce n'est pas un problème, mais je voudrais faire quelques tests avant de nourrir les images jpeg ou gif.
  • La compression se fait côté serveur avant d'être envoyé ainsi, si le client est en train d'essayer de télécharger une très grande page web, alors essentiellement de l'application web de charge de la totalité de la page dans la mémoire, la compresse et l'envoie. Si la consommation de mémoire sur le serveur-côté est un problème, alors je suggère de mettre en œuvre le code de compression dans un TStream classe dérivée qui comprime lorsque vous lisez à partir d'elle. De cette façon, la compression se fait à la volée, comme les données sont envoyées et peut être alimenté directement sur le disque par le biais de la bibliothèque de compression pour le client. Classes pour ce faire sont disponibles sur ma page d'accueil dans le package appelé StreamFilter.









Riding the bandwagon internet


Riding the bandwagon internet : Plusieurs milliers de conseils pour vous faciliter la vie.


l'Envoi de grandes pages de HTML n'est plus un probleme maintenant que nous pouvons vous envoyer les pages comprime !

Apres deux semaines non-stop de la programmation, votre application web est pret et teste. Tout est OK et les sourires sur vos clients est confronte a vous rappeler dans une drole de façon de 'Jaws'. Sauf pour une chose. Quelqu'un dans le dos timidement demande si quelque chose pouvait etre fait pour accelerer la page de resultat de recherche qui contient beaucoup de texte. A cet instant, vous savez que vous devriez avoir apporte une copie complete de l'application avec vous au lieu de demonstration au-dessus de votre 33.6 ko ligne modem au travail.

Mais tout n'est pas perdu. Il y a des moyens de reduire la quantite de donnees que vous devez envoyer au client, et je ne parle pas de la transmission de moins d'informations, mais plutot sur l'envoi de donnees compressees. Semble interessant? Lire la suite et en savoir plus.

Frivole assumptionsSince cet article decrit les fonctionnalites et les techniques qui seront ajouter a la complexite d'une application web, il est suppose que vous savez deja comment creer une application web, plus precisement une dll ISAPI, ainsi que la façon dont une telle application fonctionne. En tant que tel, je vais sauter sur quelques details, mais rassurez - vous, je vais vous presenter toutes les options et le code necessaire specifiquement pour les techniques que nous mettons en œuvre ici.

Avec cela a l'esprit, nous allons aller serrer quelques plus de jus de vos good ol' Internet en ligne.

Comment est la magie fait?Comment est-ce possible me direz-vous? Vous avez probablement a un moment ou a un autre de telechargement un fichier compresse seulement pour trouver que votre navigateur en quelque sorte interprete les donnees sous la forme d'une page web ou un texte et affiche sur votre ecran dans toute sa gloire. Pas une belle image pour dire le moins. Si vous etiez a compresser les donnees avant de les envoyer au client, ne serait-ce pas un aspect tout aussi etrange? Pas tout a fait, seulement assurez-vous que le client sait qu'il doit traiter differemment.

Le secret est cache a l'interieur les donnees que le client envoie au serveur et a l'interieur des donnees, le serveur repond avec. Il est appele Codage de Contenu. En bref, vous pouvez coder les donnees de votre application renvoie au client, et la seule precaution que vous devez prendre est de s'assurer que le client sait comment gerer les donnees dans l'encodage au format de votre choix. Ce tour est simple depuis que le client vous dit que les formats qu'il peut gerer quand il envoie la demande au serveur.

Donc ce que tout se resume a de la, est que vous devez prendre les mesures suivantes si vous souhaitez encoder les donnees renvoyees au client:

  1. Verifier si le client peut gerer le type de codage que vous souhaitez utiliser
  2. Encoder les donnees dans le format choisi
  3. Retour a la nouvellement donnees codees et dire au client quel format que vous avez code en

Quel format dois-je utiliser?Nous nous interessons en compressant les donnees que nous le retourner au client. Il y a un type de codage specifiquement pour cet usage, et son nom est 'degonfler'. L'algorithme de compression utilise dans le degonfler type de codage correspond a l'algorithme de la bibliotheque de compression zLib met en œuvre. Vous pouvez lire plus au sujet de cette bibliotheque ici: http://www.cdrom.com/pub/infozip/zlib ou consultez la rfc decrivant l'algorithme et c'est un format binaire ici: http://www.funet.fi/pub/doc/rfc/rfc1950.txt.

Bien que vous pourriez penser que vous avez deja les fichiers necessaires pour l'utilisation de la bibliotheque de compression zLib - vous ne l'avez pas! Au moins, pas exactement. Meme si le Delphi CD d'installation livre avec une copie de la bibliotheque de compression zLib dans le formulaire de pre-compile les fichiers objets et certains d'importer des fichiers, ils se cachent les details, nous devons utiliser. Plus sur cela plus tard, mais pour l'instant laissez?s il suffit de dire que nous avons besoin d'une meilleure interface pour la bibliotheque et pour cela j'ai choisi de vous livrer ma propre zLib unitaires des importations et un lien de telechargement du fichier dll: http://www.winimage.com/zLibDll/.

Comme pour le 'deflate' encodage de type Microsoft Internet Explorer s'affiche a gerer et encore, seulement les versions ulterieures (version 4 et gere pour vous, rien en dessous qui n'est pas sûr). Ce n'est pas un gros probleme, toutefois, etant donne que les autres navigateurs comme Netscape, ne dis pas qu'ils peuvent gerer la compression type de codage. Dans ce cas, notre application web ne serait tout simplement pas de retour avec les donnees compressees. La seule difference peut-etre un peu plus de temps a telecharger les donnees au client. Ce n'est pas pire que ce que nous avons aujourd'hui, donc je pense qu'on peut vivre avec ça.

Ok, j'ai recupere les fichiers, maintenant ce qui?Maintenant, il est temps de descendre les details sanglants. Nous allons prendre un bon de commencer par creer un nouveau projet ISAPI dans Delphi 5 et voir ou cela nous mene. Vous devez ajouter le fichier telecharge unitaires a l'importation de ce projet. La dll que vous venez de telecharger peut etre mis soit dans le C:\Winnt\System32 repertoire (ou de votre repertoire) ou dans le meme repertoire que votre application web.

Apres la creation du nouveau projet, nous allons ajouter un peu d'action, litteralement. Ajouter une action pour le module web et de creer un gestionnaire d'evenements vide. Faire de l'action l'action par defaut, car c'est juste une demo de l'application pour essayer notre nouveau mode de renvoi de donnees.

Nous avons maintenant un vide d'action gestionnaire d'evenements pour laisser?s ajouter un peu de code pour elle qui va faire ce dont nous avons besoin. Je vais vous montrer le gestionnaire d'evenement complet en premier et ensuite je vais aller dans les details.

procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject Demande: TWebRequest Reponse: TWebResponse var
Manipule: Boolean)
var
PlaintextStream : TStream
CompressedStream : TStream
demarrer
si ( ClientAcceptsDeflate( Demande ) )
demarrer
// 1. Tout d'abord, creer des cours d'eau temporaires avec les donnees de retour
PlaintextStream := TStringStream.Creer ('Ce texte est compresse')

// 2. Deuxiemement, creer des cours d'eau temporaires pour nos donnees compressees
CompressedStream := TMemoryStream.Creer

// 3. Maintenant compresser le flux...
zLibCompressStream( PlaintextStream, CompressedStream )

// ... et le retour
CompressedStream.Position := 0
la Reponse.ContentStream := CompressedStream
sauf
FreeAndNil( CompressedStream )
augmenter
fin // essayez de sauf - eviter les fuites de memoire
enfin
// 4. Enfin de ranger l'objet temporaire
FreeAndNil( PlaintextStream )
fin // essayez de enfin - detruire en clair un objet de flux
la Reponse.ContentType := 'text/plain'
la Reponse.ContentEncoding := 'deflate'
la Reponse.StatusCode := 200
Manipule := True
fin// si le client accepte que les donnees compressees
else begin
la Reponse.Contenu : = 'Non compresse'
la Reponse.ContentType := 'text/plain'
la Reponse.StatusCode := 200
Manipule := True
fin // si le client n'accepte pas les donnees compressees
fin // procedure TWebModule1.WebModule1ActionItem1Action

Le principal if ici determine si oui ou non le client peut gerer la compression de donnees et les envoie ensuite compresse ou non compresse des donnees vers le client en consequence. Les donnees non compressees sont traitees comme vous l'avez toujours traite les donnees dans une application web, donc nous n'allons pas en discuter davantage. Au lieu de cela, nous allons nous concentrer sur la si-alors partie de l'if qui gere les donnees compressees. Vous avez probablement remarque que nous sommes a l'aide de deux nouvelles procedures/fonctions ici, a savoir ClientAcceptsDeflate et zLibCompressStream. Je vais plus loin dans cet article.

en Supposant que nous avons une procedure qui prend un flux d'entree, compresse les donnees de ce volet tient et ecrit les donnees compressees dans un flux de sortie, nous pouvons decrire le code ci-dessus comme ceci:

  1. tout d'Abord creer un cours d'eau temporaire contenant ce que nous voulons retourner au client
  2. Deuxiemement, compresser ces donnees et de mettre les donnees compressees a un nouveau flux de donnees
  3. Ce nouveau courant, la tenue de nos donnees compressees, il nous suffit de retourner sur le client
  4. Enfin, nous avons range nos objets temporaires

Vous pouvez trouver la correspondance des points de cette liste dans le numerotes commentaires ci-dessus gestionnaire d'evenement. Il est assez simple de code, et il doit etre trop depuis que nous avons cache les details sanglants dans les deux fonctions, dont nous parlerons ensuite.

Une chose a noter est que, une fois que nous attribuer le ContentStream propriete de l'objet de la Reponse a notre flux de la reponse-objet prend en charge le flux de donnees. Une fois les donnees de reponse a ete envoyee au client le flux sera libere pour nous, alors nous devons nous assurer de ne pas accidentellement gratuit nous-memes. Dans le cas d'une exception cependant, je fais l'hypothese que la cession s'est detraque et ainsi liberer le flux avant la propagation de l'exception plus haut.

Parlez-vous français?Pour determiner si le client sait comment gerer les donnees compressees nous devons prendre un regard sur les donnees qu'il nous envoie en premier lieu. Typique du web demande ressemble a ceci (faux demande, de sorte que les details peuvent ne pas etre 100% correct):

GET /index.html HTTP/1.0
Accept-Types: */*
Accept-Encoding: gzip, deflate
User-Agent: Mozilla 4.0 (Microsoft Internet Explorer 5.0 (Compatible NT)

Ce qui nous interesse c'est la ligne qui va de Accept-Encoding: gzip, deflate. Il nous dit quels types d'encodage, le client est en mesure d'accepter, et dans ce cas, il peut accepter des donnees encodees dans le format gzip ainsi que le degonfler format. Ce dernier est l'un nous devons, donc, nous allons voir comment faire pour obtenir que la connaissance de l'interieur de notre application web. La fonction ressemble a ceci:

La fonction que nous avons besoin d'ecrire ressemble a ceci:

fonction ClientAcceptsDeflate( const Demande: TWebRequest ): Boolean
var
EncodingTypes : string
demarrer
// reformater liste des types d'encodage de la requete
EncodingTypes := Request.GetFieldByName( 'HTTP_ACCEPT_ENCODING' )
EncodingTypes := Majuscule( StringReplace( EncodingTypes, ',', '/', [ rfReplaceAll ] ) )
EncodingTypes := '/' StringReplace( EncodingTypes, ' ', ', [ rfReplaceAll ] ) '/'

// Retourne le drapeau
Result := ( Pos( '/DEGONFLAGE/', EncodingTypes ) > 0 )
fin // fonction ClientAcceptsDeflate

bref j'ai reformater les valeurs de gzip, deflate dans /GZIP/DEFLATE/, puis verifiez si la chaîne de caracteres /DEGONFLAGE/ se trouve en son sein. Si vous etes interesse a savoir ce que les autres champs peuvent etre trouves dans la requete, alors je vous suggere de prendre un coup d'oeil a http://msdn.microsoft.com/library/psdk/iisref/isre504l.htm et l'utilisation de la ALL_HTTP variable pour verifier que les variables le client envoie.

Naturellement, parlons!Apres nous avons determine que le client peut en effet gerer des donnees compressees tout ce que nous avons a faire, c'est en fait de produire les donnees compressees et c'est la que le magie entre.

Comme indique precedemment, nous allons utiliser la bibliotheque de compression zLib pour faire de la compression. Le code comprend les etapes suivantes:

  1. mettre en place des tampons pour l'alimentation des donnees vers le moteur ainsi que d'accepter les donnees compressees a partir de
  2. Initialiser le moteur de compression
  3. Alimentation des donnees en texte brut dans le tampon d'entree du flux d'entree
  4. Compresser la memoire tampon d'entree de la memoire tampon de sortie
  5. Ecrire des donnees a partir de la memoire tampon de sortie pour le flux de sortie
  6. Repetez les etapes 3 a 5 jusqu'a ce que plus de donnees dans le flux d'entree et de tampons ont ete vides
  7. Fermer le moteur de compression

nous allons creuser dans les details et voir ce que nous avons a faire face:

procedure zLibCompressStream( const de la Source, de la Destination: TStream )
var
z_s : z_stream
rc : Integer
// 1. Les tampons d'entree et de sortie
SourceBuffer : array[ 0..BufferSize-1 ] de Byte
DestinationBuffer : array[ 0..BufferSize-1 ] de Byte
demarrer
// 2. Preparer la zLib enregistrement des donnees
z_init_zstream( z_s )
z_s.next_in := @SourceBuffer
z_s.next_out := @DestinationBuffer
z_s.avail_out := BufferSize

// 2. Initialiser le moteur de compression
deflateInit2( z_s, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY )

// Maintenant compresser le flux

repeat
// 3. Voir si nous sommes arrives a nourrir plus de donnees vers le moteur de compression
si ( z_s.avail_in = 0 ) et ( Source.Position < Source.Taille )
demarrer
z_s.next_in := @SourceBuffer
z_s.avail_in := Source.Lire( SourceBuffer, Buffersize )
fin // si les donnees d'entree completement epuisee

// 4. Compresser les donnees
si ( z_s.avail_in = 0 )
rc := degonfler( z_s, Z_FINISH )
else
rc := degonfler( z_s, Z_STREAM_END )

// 5. Verifier si nous avons obtenu des donnees compressees pour ecrire a destination
si ( z_s.avail_out = 0 ) ou ( rc = Z_STREAM_END )
demarrer
Destination.WriteBuffer( DestinationBuffer, BufferSize - z_s.avail_out )
z_s.avail_out := BufferSize
z_s.next_out := @DestinationBuffer
fin // si obtenu des donnees disponibles pour l'ecriture

// 6. Repetez jusqu'a ce que les tampons epuise
au ( rc <> Z_OK ) ou ( ( rc = Z_STREAM_END ) et ( z_s.avail_out = BufferSize ) et ( z_s.avail_in = 0 ) )
enfin
// 7. Nettoyer le moteur donnees
deflateEnd( z_s )
fin // essayez enfin de nettoyer apres le moteur
fin // procedure zLibCompressStream

Comme avant, vous pouvez faire correspondre les points de cette liste avec le numero commentaires ci-dessus. La raison pour laquelle nous ne pouvions pas utiliser la zLib code?s inclus avec Delphi est qu'il cache la deflateInit2 routine et les parametres necessaires a l'interieur de la mise en œuvre de la partie de l'unite ainsi que de ne pas s'exposer a tout le code necessaire.

afin de produire des donnees compressees de maniere a ce que le navigateur peut gerer, nous avons besoin de compresser les donnees sans enregistrement d'en-tete. L'enregistrement d'en-tete est un petit enregistrement de l'information qui est ecrit au tout debut de la compression de donnees et aide le moteur a decompression savoir la quantite de donnees qui suit. Nous pouvons choisir de ne pas ecrire cet enregistrement d'en-tete en passant une valeur negative pour la wBitSize parametre a la deflateInit2 procedure. Depuis le degonfler standard que les navigateurs respectent, ne s'attend pas, ni ne sait comment gerer cette en-tete, nous avons a filtrer. Puisque nous ne pouvions pas appeler deflateInit2 directement avec zLib code fourni avec Delphi, nous avons dû recourir a une complete de dll exemplaire de la bibliotheque de compression.

Le moteur de compression est capable de compresser les donnees de la memoire tampon d'entree et l'ecrire dans le tampon de sortie. Lors de la sortie de la memoire tampon est pleine, notre code de vider cette memoire tampon et d'ecrire les donnees a la destination, dans notre cas d'un ruisseau. Quand il a reussi a compresser toutes les donnees de la memoire tampon d'entree, notre code doit remplir la memoire tampon de nouveau avec autant de donnees que possible. Le moteur de compression prend en charge le reste.

les Tests itAfter de la compilation de votre application web (voir en bas de l'article pour une copie de l'exemple de projet mis en œuvre dans cet article), vous devez idealement tester avec un navigateur qui gere les donnees compressees et avec celui qui ne l'est pas. Vous pouvez utiliser Internet Explorer 4 et 5 que l'ancien et Netscape 4.06 que les derniers. Le navigateur qui gere la compression doit afficher le texte 'Ce texte est compresse' et l'autre 'Non compresse' a des fins de verification.

Moyenne des taux de compression sur la base de texte contenu est d'environ 5-6 fois (de 15 a 20% de la taille originale) de sorte que l'effet doit etre clairement visible sur de grandes pages web.

en l'Enveloppant une resurgence, c'est tout. Avec le code et les connaissances contenues dans cet article, vous devriez maintenant etre en mesure de traiter les donnees compressees a partir de votre application web. Meme si nous avons cree une dll ISAPI dans cet article, la theorie et le code doit rester la meme pour les CGI et NSAPI applications.

j'ai pris la liberte de creer une unite avec les deux fonctions decrites ci-dessus, ainsi qu'une copie de l'exemple produits dans cet article. Vous pouvez telecharger les fichiers a partir de la liste ci-dessous. Si il y a des suggestions ou des choses que vous aimeriez commenter je peux etre atteint a [email protected].

les Fichiers a telecharger:

  • zLib dll (a partir du site web d'auteurs)
  • Importer unite pour zLib.dll
  • Exemple de projet (y compris l'unite avec les deux fonctions ainsi que l'importation de l'unite)
  • Uniquement l'appareil avec les deux fonctions que nous avons ecrit

Il ya un couple de finition notes de garder a l'esprit:

  • Le moteur de compression ne permet pas de determiner si les donnees se prete facilement a la compression ou pas avant qu'il ne commence a macher sur elle. Cela signifie qu'il est possible de fournir des donnees par le biais de ce qui ne peut etre compresse et pourrait meme augmenter en taille. Pour du texte et des pages web ce n'est pas un probleme, mais je voudrais faire quelques tests avant de nourrir les images jpeg ou gif.
  • La compression se fait cote serveur avant d'etre envoye ainsi, si le client est en train d'essayer de telecharger une tres grande page web, alors essentiellement de l'application web de charge de la totalite de la page dans la memoire, la compresse et l'envoie. Si la consommation de memoire sur le serveur-cote est un probleme, alors je suggere de mettre en œuvre le code de compression dans un TStream classe derivee qui comprime lorsque vous lisez a partir d'elle. De cette façon, la compression se fait a la volee, comme les donnees sont envoyees et peut etre alimente directement sur le disque par le biais de la bibliotheque de compression pour le client. Classes pour ce faire sont disponibles sur ma page d'accueil dans le package appele StreamFilter.


Riding the bandwagon internet

Riding the bandwagon internet : Plusieurs milliers de conseils pour vous faciliter la vie.
Recommander aux amis
  • gplus
  • pinterest

Messages récents

Commentaire

Laisser un commentaire

évaluation