Den Internet-Zug fahren


Senden große HTML-Seiten ist nicht mehr ein Problem, jetzt, da wir die Seiten komprimiert senden können!

Nach zwei Wochen der nonstop-Programmierung ist Ihre Webanwendung bereit und getestet. Alles ist a-OK und die Grinsen auf den Gesichtern Ihrer Kunden erinnern, auf seltsame Weise 'Jaws'. Außer eine Sache. Zaghaft fragt jemand in den Rücken wenn etwas getan werden könnte, dass Suchergebnisseite beschleunigen, die so viel Text enthält. In diesem Augenblick wissen Sie, dass Sie eine vollständige Kopie der Anwendung mit Ihnen statt demonstrieren es über Ihre 33,6 kb-Modem-Leitung bei der Arbeit gebracht haben sollte.

Aber nicht alles verloren ist. Es werden Möglichkeiten zur Verringerung der Datenmenge, die an den Client gesendet werden sollen, und ich spreche nicht über weniger Informationen zu übermitteln, sondern um senden komprimierte Daten. Klingt interessant? Lesen Sie weiter und erfahren Sie wie.

Frivole AssumptionsSince dieser Artikel beschreibt Funktionen und Techniken, die die Komplexität einer Webanwendung hinzufügen werden, wird davon ausgegangen, dass Sie bereits Gewusst wie: Erstellen einer Webanwendung, speziell einer ISAPI-Dll als auch wissen, wie solch eine Anwendung funktioniert. Als solche wird ich einige Details überspringen, aber seien Sie versichert - ich präsentieren euch mit allen Optionen und Code erforderlich, die speziell für die Techniken, die wir hier implementiert wird.

In diesem Sinne lass uns etwas mehr Saft aus Ihrer guten ol ' Internet-Standleitung squeeze.

Wie erfolgt die Magie? Wie ist dies möglich, Fragen Sie? Sie haben wahrscheinlich auf einmal oder andere heruntergeladen eine komprimierte Datei, nur um zu erfahren, dass Ihr Browser irgendwie die Daten als Webseite oder als Text interpretiert und dies auf Ihrem Bildschirm in seiner ganzen Pracht angezeigt. Kein schönes Bild, gelinde gesagt. Würden Sie die Daten zu komprimieren, bevor sie an den Client gesendet, aussehen würde nicht es dann genau so seltsam? Nicht ganz, nur stellen Sie sicher, dass der Client weiß, dass es anders behandelt werden soll.

Das Geheimnis verbirgt sich sowohl die Daten, die der Client an den Webserver sendet und in die Daten, die, denen der Webserver antwortet mit. It's called Inhaltskodierung. Kurz gesagt, können Sie die Daten codieren, die Ihre Anwendung an den Client, und die einzige Vorsichtsmaßnahme, die Sie brauchen zurück zu nehmen ist sicherzustellen, dass der Client weiß, wie man die Daten in das Codierung Format zu behandeln, die Sie wählen. Dies ist wiederum einfach, da der Client Ihnen welche Formate damit umgehen sagt, kann wenn die Anforderung an den Server gesendet.

Also was alles nach unten läuft darauf hinaus, ist, dass Sie die folgenden Schritte ausführen, wenn Sie die Daten zu codieren möchten müssen an den Client zurückgegeben:

  1. Prüfen Sie, ob der Client den Codierungstyp umgehen kann, die, den Sie verwenden möchten
  2. Die Daten im ausgewählten Format codieren
  3. Zurückgeben Sie die neu codierten Daten und sagen Sie dem Client zu, welches Format haben Sie es in codiert

Welches Format sollte ich verwenden? Wir interessieren uns Komprimieren der Daten, die wir an den Client zurückgeben. Speziell für diesen Zweck gibt es ein Codierungstyp, und ihr Name ist 'deflate'. Der Kompressionsalgorithmus in den Codierungstyp Deflate entspricht der Algorithmus, den die zLib-Komprimierung-Bibliothek implementiert. Lesen Sie mehr über diese Bibliothek hier: https://www.cdrom.com/pub/infozip/zlib oder die Rfc beschreiben den Algorithmus zu überprüfen und es ist binär-Format hier: https://www.funet.fi/pub/doc/rfc/rfc1950.txt.

Obwohl Sie denken vielleicht, dass Sie die Dateien bereits für die Verwendung der zLib Kompressionsbibliothek erforderlich - Sie nicht! Zumindest nicht genau. Obwohl die Delphi-Installations-CD mit einer Kopie der zLib Kompressionsbibliothek in Form von vorkompilierten Objektdateien und einige Importdateien kommt, verstecken sie die Details, die wir nutzen müssen. Mehr dazu später, aber für jetzt lassen Sie? s es genügt um zu sagen, wir brauchen eine bessere Schnittstelle zur Bibliothek und für die, die ich erwählt habe, mein eigenes zLib-Import-Einheit und einen Link zu den herunterladbaren vorkompilierte Dll liefern: https://www.winimage.com/zLibDll/.

Wie bei der 'verkleinern' Codierungstyp nur Microsoft Internet Explorer scheint es und wieder nur die höheren Versionen behandelt (Version 4 und oben behandelt es sicher, alles darunter ist unsicher). Dies ist kein großes Problem, jedoch seit den anderen Browsern wie Netscape, sagen sie die Komprimierung Codierungstyp behandeln können nicht. In diesem Fall wäre nicht unsere Webanwendung einfach mit komprimierten Daten zurück. Der einzige Unterschied wäre ein wenig länger, um die Daten an den Client herunterladen. Dies ist nicht schlimmer als das, was wir heute haben, so dass ich denke, dass wir damit leben können.

O.k., ich habe die Dateien jetzt was? Jetzt ist es Zeit, um die blutigen Details unten. Lassen Sie uns einen guten Start durch Erstellen eines neuen ISAPI-Projekts in Delphi 5 steigen und sehen, wo das uns braucht. Sie sollten dieses Projekt als auch das heruntergeladene Import-Gerät hinzufügen. Die Dll, die Sie gerade heruntergeladen kann entweder in das C:\Winnt\System32 Verzeichnis (oder das entsprechende Verzeichnis) oder im selben Verzeichnis wie Ihre Webanwendung gesetzt werden.

Fügen Sie nach dem Erstellen des neuen Projekts wollen wir einige Aktion hinzu, buchstäblich. Das Web-Modul fügen Sie eine Aktion hinzu, und erstellen Sie einen leeren Ereignishandler für es. Machen Sie der Aktion sowie die Standard-Aktion, da dies nur eine Demoanwendung für unsere neue Art der Rückgabe von Daten ausprobieren.

Wir haben jetzt einen leeren Aktion-Ereignishandler lassen? s fügen Sie Code hinzu, die es tun, was müssen wir machen. Ich zeige den complete-Ereignis-Handler erste und dann gehe ich durch die Details.

Verfahren TWebModule1.WebModule1WebActionItem1Action (Sender: TObject; Anforderung: TWebRequest; Antwort: TWebResponse; var
Behandelt: Boolean);
var
PlaintextStream: TStream;
CompressedStream: TStream;
beginnen
if (ClientAcceptsDeflate (Anfrage)) dann
beginnen
// 1. Erstellen Sie zunächst temporären Streams mit zurückzugebenden Daten
PlaintextStream: = TStringStream.Create ('dieser Text ist komprimiert');
versuchen Sie
// 2. Zweitens erstellen Sie temporärer Stream für unsere komprimierten Daten
CompressedStream: = TMemoryStream.Create;
versuchen Sie
// 3. Jetzt komprimieren Sie den Stream...
zLibCompressStream (PlaintextStream, CompressedStream);

... und wieder
CompressedStream.Position: = 0;
Response.ContentStream: = CompressedStream;
mit Ausnahme von
FreeAndNil (CompressedStream);
erhöhen;
end; / / try - außer Speicherverluste zu vermeiden
Schließlich
// 4. Temporäres Objekt endlich Aufräumen
FreeAndNil (PlaintextStream);
end; schließlich versuchen - nur-Text-Stream-Objekt zu zerstören
Response.ContentType: = ' Text/Plain';
Response.ContentEncoding: = 'verkleinern';
Response.StatusCode: = 200;
Behandelt: = True;
Ende / / Wenn Client komprimierte Daten akzeptiert
sonst beginnen
Response.Content: = 'Nicht komprimiert';
Response.ContentType: = ' Text/Plain';
Response.StatusCode: = 200;
Behandelt: = True;
end; / / Wenn Client nicht komprimierte Daten akzeptiert
end; / / Verfahren TWebModule1.WebModule1ActionItem1Action

Hier die primäre If-Anweisung bestimmt, ob der Client verträgt die komprimierten Daten und sendet dann entweder komprimiert oder unkomprimiert Daten zurück an den Client entsprechend. Die unkomprimierten Daten werden behandelt, wie Sie Daten in einer Webanwendung immer behandelt haben, so dass wir, die wird nicht weiter diskutieren. Stattdessen werden wir auf der wenn-dann-Teil der If-Anweisung zu konzentrieren, die komprimierte Daten behandelt. Sie bemerkt wahrscheinlich, dass wir zwei neue Prozeduren/Funktionen hier, nämlich ClientAcceptsDeflate und zLibCompressStream verwenden. Ich gehe durch die weiter unten in diesem Artikel.

Angenommen, wir haben eine Prozedur, die einen Stream als Eingang, komprimiert die Daten annimmt, die diesen Stream hält und schreibt die komprimierten Daten in einen Stream als Ausgang, können wir den Code oben gezeigt wird, wie folgt beschreiben:

  1. Erstellen Sie zunächst einen temporären Streams enthalten, was wir an den Client zurückgeben möchten
  2. Zweitens, komprimieren Sie diese Daten zu und setzen Sie die komprimierten Daten in einen neuen stream
  3. Diese neuen Stream, halten unsere komprimierten Daten, wir geben einfach zurück an den client
  4. Schließlich Aufräumen wir unserer temporäre Objekte

Die übereinstimmende Punkte dieser Liste finden Sie in den nummerierten Kommentaren in den oben genannten Ereignishandler. Es ist ziemlich einfach Code, und sollte auch da haben wir versteckt, die blutigen Details in zwei Funktionen, die wir weiter diskutieren.

Zu bemerken ist, dass sobald wir unseren Stream die ContentStream-Eigenschaft des Response-Objekts zuweisen das Antwort--Objekt Eigentümer des Streams wird. Nachdem die Antwortdaten an den Client Stream gesendet wurde für uns freigegeben wird, so dass wir sicherstellen müssen wir nicht versehentlich es uns befreien. Im Falle einer Ausnahme aber ich davon aus, dass die Zuordnung drunter und drüber ging und somit den Stream vor propagieren die Ausnahme, die weiter oben freizugeben.

Parlez-Vous Français? Um festzustellen, ob der Client weiß, wie komprimierte Daten zu behandeln, die wir einen Blick auf die Daten müssen, sendet er uns an erster Stelle. Eine typische Webanforderung sieht diese (gefälschte Anfrage, so dass die Informationen möglicherweise nicht 100 % richtig):

/ Index.html HTTP/1.0 erhalten
Akzeptieren-Typen: * / *
Accept-Encoding: Gzip, deflate
Benutzer-Agent: Mozilla 4.0 (Microsoft Internet Explorer 5.0 Compatible; NT)

Was wir interessiert, ist die Linie, die geht Accept-Encoding: Gzip, deflate. Es sagt uns, welche Kodierung des Clients akzeptieren kann, und in diesem Fall im Gzip-Format sowie das Deflate-Format codierte Daten annehmen kann. Letzteres ist der, den wir wir also sehen brauchen, wie Sie dieses Wissen aus innerhalb unserer Web-Anwendung zu erhalten. Die Funktion sieht wie folgt aus:

Die Funktion müssen wir schreiben sieht wie folgt aus:

Funktion ClientAcceptsDeflate ( const Anforderung: TWebRequest): Boolean;
var
EncodingTypes: String;
beginnen
Erhalten Sie und neu formatieren Sie Liste Codierungstypen aus der Anforderung
EncodingTypes: = Request.GetFieldByName ('HTTP_HOST');
EncodingTypes: = UpperCase (StringReplace (EncodingTypes, ',', '/', [RfReplaceAll]));
EncodingTypes: = '/' + StringReplace (EncodingTypes, ' ', '', [RfReplaceAll]) + '/';

Rückkehr der Flagge
Ergebnis: = (Pos ('/ entlüften /', EncodingTypes) > 0);
Ende; / / Funktion ClientAcceptsDeflate

Kurz ich die Werte Gzip, deflate in /GZIP/DEFLATE/formatieren und dann überprüfen Sie, ob die Zeichenfolge /DEFLATE/ in ihm gefunden wird. Bist du interessiert zu wissen, sendet welche anderen Feldern in der Anforderung gefunden werden können, dann schlage ich vor, Sie werfen Sie einen Blick auf https://msdn.microsoft.com/library/psdk/iisref/isre504l.htm und verwenden Sie die ALL_HTTP-Variable, welche Variablen überprüfen den Client tatsächlich.

Naturellement, Parlons! Nachdem wir festgestellt haben, dass der Client tatsächlich alle komprimierte Daten verarbeiten kann, was, die wir haben, ist Links zu tun eigentlich die komprimierten Daten zu produzieren und die Magie kommt.

Wie bereits erwähnt, verwenden wir die zLib Kompressionsbibliothek um zu tun, die eigentlich komprimieren. Der Code umfasst folgende Schritte:

  1. Puffer für die Einspeisung von Daten an das Modul eingerichtet sowie komprimierte Daten daraus zu akzeptieren
  2. Kompressionsengine initialisieren
  3. Nur-Text-Daten in den Eingabepuffer aus dem Eingabestream einfließen
  4. Komprimieren des Eingabepuffers in den Ausgabepuffer
  5. Schreiben von Daten aus den Ausgabepuffer in den Ausgabestream geschrieben
  6. Wiederholen Sie Schritte 3 bis 5, bis keine Daten mehr im Eingabestream und Puffer geleert haben
  7. Enge Kompressionsengine

Wir graben in die Details und sehen, was wir zu bewältigen haben:

Procedure zLibCompressStream ( const Quelle, Ziel: TStream);
var
Z_s: Z_stream;
RC: Integer;
// 1. Puffer für ein- und Ausgabe
SourceBuffer: Array[0..BufferSize-1] von Byte;
DestinationBuffer: Array[0..BufferSize-1] von Byte;
beginnen
// 2. Vorbereiten des zLib-Datensatzes
Z_init_zstream (Z_s);
z_s.next_in: = die @SourceBuffer;
z_s.next_out: = die @DestinationBuffer;
z_s.avail_out: = BufferSize;

// 2. Kompressionsengine initialisieren
deflateInit2 (Z_s, Z_BEST_COMPRESSION, Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY);

Jetzt komprimieren Sie den stream
versuchen Sie
Wiederholen Sie die
// 3. Sehen Sie, wenn wir weitere Daten zum Motor Kompression zu füttern
if (z_s.avail_in = 0) und (Source.Position < Source.Size) dann
beginnen
z_s.next_in: = die @SourceBuffer;
z_s.avail_in: = Source.Read (SourceBuffer, Buffersize);
end; / / Wenn Eingabedaten völlig erschöpft

// 4. Komprimierung der Daten
if (z_s.avail_in = 0) dann
RC: = entlüften (Z_s, Z_FINISH)
sonst
RC: = entlüften (Z_s, Z_STREAM_END);

// 5. Prüfen Sie, ob wir komprimierte Daten schreiben zum Ziel haben
if (z_s.avail_out = 0) or (rc = Z_STREAM_END) dann
beginnen
Destination.WriteBuffer (DestinationBuffer, BufferSize - z_s.avail_out);
z_s.avail_out: = BufferSize;
z_s.next_out: = die @DestinationBuffer;
end; / / Wenn die verfügbaren Daten zum Schreiben bekam

// 6. Wiederholen Sie, bis die Puffer leer
bis (Rc-<>-Z_OK) or ((rc = Z_STREAM_END) und (z_s.avail_out = BufferSize) und (z_s.avail_in = 0));
Schließlich
// 7. Die Motordaten bereinigen
DeflateEnd (Z_s);
end; / / versuchen schließlich - nach Motor Aufräumen
end; / / Verfahren zLibCompressStream

Als können vor, Sie die Punkte aus dieser Liste mit den nummerierten Kommentaren oben entsprechen. Der Grund, wir können nicht die zLib zu codieren, die? s mit Delphi enthalten ist, dass es die deflateInit2-Routine und die erforderlichen Parameter im Implementierungsteil des Referats auch nicht den erforderlichen Code offenlegen verbirgt.

Um komprimierte Daten zu erzeugen, die der Browser behandeln kann, müssen wir die Daten mit keine Kopfzeilen-Datensatz zu komprimieren. Im Header-Eintrag ist ein kleiner Datensatz, wird zu Beginn des komprimierten Daten geschrieben und hilft die Dekompression-Engine, die wissen, wie viel Daten, die folgt. Wir können entscheiden, um diese Kopfzeilen-Datensatz nicht zu schreiben, indem Sie einen negativen Wert für den wBitSize-Parameter an die deflateInit2-Prozedur übergeben. Da die Deflate-Standard, der den Browser an, halten erwartet nicht, noch weiß, wie man diesen Header zu behandeln, müssen wir es herausfiltern. Da wir nicht direkt mit dem zLib-Code deflateInit2 nennen könnte, die mit Delphi kam mussten wir auf eine vollständige Dll Kopie die Kompressionsbibliothek zurückgreifen.

Die Kompression-Engine kann der Komprimierung der Daten aus dem Eingabepuffer und in Ausgabepuffer schreiben. Wenn der Ausgabepuffer voll ist, unser Code muss diesen Puffer spülen und schreiben die Daten darin zum Ziel, in unserem Fall einen Stream. Wenn es gelungen ist, alle Daten aus den Eingabepuffer zu komprimieren, muss unser Code, um den Puffer wieder mit so viele Daten wie möglich zu füllen. Kompressionsengine übernimmt den Rest.

Testen Sie ItAfter Ihre Webanwendung kompilieren (siehe unten Artikel für eine Kopie des Projektes Beispiel in diesem Artikel implementiert) Sie sollten idealerweise durch Tests mit beiden einen Browser, der komprimierte Daten verarbeitet und eine, die nicht. Sie können Internet Explorer 4/5 als erstere und Netscape 4.06 als letztere. Die Browser, die Kompression behandelt sollte zeigen den Text 'dieser Text wird komprimiert' und eine 'nicht komprimiert' zur Überprüfung.

Durchschnittliche Komprimierungsverhältnis auf textbasierte Inhalte ist ca. 5 - 6 mal (15-20 % der ursprünglichen Größe) so die Wirkung sollte auf großen Webseiten deutlich bemerkbar.

Wickeln es upWell, das war's. Mit dem Code und in diesem Artikel enthaltene wissen sollten Sie nun komprimierte Daten aus Ihrer Webanwendung behandeln. Obwohl wir in diesem Artikel eine ISAPI-Dll erstellt, sollte die Theorie und den Code auch für CGI und NSAPI Anwendungen unverändert.

Ich habe die Freiheit eine Einheit mit den beiden oben beschriebenen Funktionen sowie eine Kopie des im Beispiel in diesem Artikel produziert erstellt genommen. Sie können die Dateien aus der Liste unten herunterladen. Wenn es irgendwelche Vorschläge oder Dinge, die Sie würde gerne kommentieren, ich unter [email protected] erreicht werden können.

Dateien zum Download:

  • zLib-Dll (von Autoren-Website)
  • Import-Einheit für zLib.dll
  • Beispiel-Projekt (einschließlich Einheit mit zwei Funktionen sowie Import-Gerät)
  • Nur das Gerät mit zwei Funktionen, die wir schrieben

Es gibt ein paar Veredelung Hinweise zu beachten:

  • Kompressionsengine bestimmt nicht, ob die Daten sich leicht, eignet Kompression oder nicht, bevor es beginnt, darauf kauen. Dadurch ist es möglich, Daten über sie zu ernähren, die nicht komprimiert werden und noch verstärken könnte Größe statt. Für Texte und Webseiten ist kein Problem allerdings, aber würde ich einige Tests vor der Fütterung von Jpegs oder Gifs hinein.
  • Die Komprimierung erfolgt serverseitig, bevor es gesendet wird, sodass Wenn der Client versucht, eine sehr große Webseite herunterzuladen dann im Wesentlichen die Webanwendung die gesamte Seite in den Arbeitsspeicher lädt, sie komprimiert und sie sendet. Wenn Speicherverbrauch auf der Serverseite ein Problem ist würde dann ich vorschlagen, Implementierung des Kompression-Codes in eine TStream abgeleitete Klasse, die komprimiert, wenn Sie daraus lesen. Dieser Weg-Komprimierung erfolgt on-the-Fly, wie die Daten gesendet und an dem Client direkt abseits der Plattenoberfläche durch die Kompressionsbibliothek gefüttert werden können. Klassen für auf diese Weise stehen auf meiner Homepage in das Paket namens StreamFilter.









Den Internet-Zug fahren


Den Internet-Zug fahren : Mehreren tausend Tipps, um Ihr Leben einfacher machen.


Senden große HTML-Seiten ist nicht mehr ein Problem, jetzt, da wir die Seiten komprimiert senden können!

Nach zwei Wochen der nonstop-Programmierung ist Ihre Webanwendung bereit und getestet. Alles ist a-OK und die Grinsen auf den Gesichtern Ihrer Kunden erinnern, auf seltsame Weise 'Jaws'. Außer eine Sache. Zaghaft fragt jemand in den Rücken wenn etwas getan werden könnte, dass Suchergebnisseite beschleunigen, die so viel Text enthält. In diesem Augenblick wissen Sie, dass Sie eine vollständige Kopie der Anwendung mit Ihnen statt demonstrieren es über Ihre 33,6 kb-Modem-Leitung bei der Arbeit gebracht haben sollte.

Aber nicht alles verloren ist. Es werden Möglichkeiten zur Verringerung der Datenmenge, die an den Client gesendet werden sollen, und ich spreche nicht über weniger Informationen zu übermitteln, sondern um senden komprimierte Daten. Klingt interessant? Lesen Sie weiter und erfahren Sie wie.

Frivole AssumptionsSince dieser Artikel beschreibt Funktionen und Techniken, die die Komplexität einer Webanwendung hinzufügen werden, wird davon ausgegangen, dass Sie bereits Gewusst wie: Erstellen einer Webanwendung, speziell einer ISAPI-Dll als auch wissen, wie solch eine Anwendung funktioniert. Als solche wird ich einige Details überspringen, aber seien Sie versichert - ich präsentieren euch mit allen Optionen und Code erforderlich, die speziell für die Techniken, die wir hier implementiert wird.

In diesem Sinne lass uns etwas mehr Saft aus Ihrer guten ol ' Internet-Standleitung squeeze.

Wie erfolgt die Magie? Wie ist dies möglich, Fragen Sie? Sie haben wahrscheinlich auf einmal oder andere heruntergeladen eine komprimierte Datei, nur um zu erfahren, dass Ihr Browser irgendwie die Daten als Webseite oder als Text interpretiert und dies auf Ihrem Bildschirm in seiner ganzen Pracht angezeigt. Kein schönes Bild, gelinde gesagt. Würden Sie die Daten zu komprimieren, bevor sie an den Client gesendet, aussehen würde nicht es dann genau so seltsam? Nicht ganz, nur stellen Sie sicher, dass der Client weiß, dass es anders behandelt werden soll.

Das Geheimnis verbirgt sich sowohl die Daten, die der Client an den Webserver sendet und in die Daten, die, denen der Webserver antwortet mit. It's called Inhaltskodierung. Kurz gesagt, können Sie die Daten codieren, die Ihre Anwendung an den Client, und die einzige Vorsichtsmaßnahme, die Sie brauchen zurück zu nehmen ist sicherzustellen, dass der Client weiß, wie man die Daten in das Codierung Format zu behandeln, die Sie wählen. Dies ist wiederum einfach, da der Client Ihnen welche Formate damit umgehen sagt, kann wenn die Anforderung an den Server gesendet.

Also was alles nach unten läuft darauf hinaus, ist, dass Sie die folgenden Schritte ausführen, wenn Sie die Daten zu codieren möchten müssen an den Client zurückgegeben:

  1. Prüfen Sie, ob der Client den Codierungstyp umgehen kann, die, den Sie verwenden möchten
  2. Die Daten im ausgewählten Format codieren
  3. Zurückgeben Sie die neu codierten Daten und sagen Sie dem Client zu, welches Format haben Sie es in codiert

Welches Format sollte ich verwenden? Wir interessieren uns Komprimieren der Daten, die wir an den Client zurückgeben. Speziell für diesen Zweck gibt es ein Codierungstyp, und ihr Name ist 'deflate'. Der Kompressionsalgorithmus in den Codierungstyp Deflate entspricht der Algorithmus, den die zLib-Komprimierung-Bibliothek implementiert. Lesen Sie mehr über diese Bibliothek hier: https://www.cdrom.com/pub/infozip/zlib oder die Rfc beschreiben den Algorithmus zu überprüfen und es ist binär-Format hier: https://www.funet.fi/pub/doc/rfc/rfc1950.txt.

Obwohl Sie denken vielleicht, dass Sie die Dateien bereits für die Verwendung der zLib Kompressionsbibliothek erforderlich - Sie nicht! Zumindest nicht genau. Obwohl die Delphi-Installations-CD mit einer Kopie der zLib Kompressionsbibliothek in Form von vorkompilierten Objektdateien und einige Importdateien kommt, verstecken sie die Details, die wir nutzen müssen. Mehr dazu später, aber für jetzt lassen Sie? s es genügt um zu sagen, wir brauchen eine bessere Schnittstelle zur Bibliothek und für die, die ich erwählt habe, mein eigenes zLib-Import-Einheit und einen Link zu den herunterladbaren vorkompilierte Dll liefern: https://www.winimage.com/zLibDll/.

Wie bei der 'verkleinern' Codierungstyp nur Microsoft Internet Explorer scheint es und wieder nur die höheren Versionen behandelt (Version 4 und oben behandelt es sicher, alles darunter ist unsicher). Dies ist kein großes Problem, jedoch seit den anderen Browsern wie Netscape, sagen sie die Komprimierung Codierungstyp behandeln können nicht. In diesem Fall wäre nicht unsere Webanwendung einfach mit komprimierten Daten zurück. Der einzige Unterschied wäre ein wenig länger, um die Daten an den Client herunterladen. Dies ist nicht schlimmer als das, was wir heute haben, so dass ich denke, dass wir damit leben können.

O.k., ich habe die Dateien jetzt was? Jetzt ist es Zeit, um die blutigen Details unten. Lassen Sie uns einen guten Start durch Erstellen eines neuen ISAPI-Projekts in Delphi 5 steigen und sehen, wo das uns braucht. Sie sollten dieses Projekt als auch das heruntergeladene Import-Gerät hinzufügen. Die Dll, die Sie gerade heruntergeladen kann entweder in das C:\Winnt\System32 Verzeichnis (oder das entsprechende Verzeichnis) oder im selben Verzeichnis wie Ihre Webanwendung gesetzt werden.

Fügen Sie nach dem Erstellen des neuen Projekts wollen wir einige Aktion hinzu, buchstäblich. Das Web-Modul fügen Sie eine Aktion hinzu, und erstellen Sie einen leeren Ereignishandler für es. Machen Sie der Aktion sowie die Standard-Aktion, da dies nur eine Demoanwendung für unsere neue Art der Rückgabe von Daten ausprobieren.

Wir haben jetzt einen leeren Aktion-Ereignishandler lassen? s fügen Sie Code hinzu, die es tun, was müssen wir machen. Ich zeige den complete-Ereignis-Handler erste und dann gehe ich durch die Details.

Verfahren TWebModule1.WebModule1WebActionItem1Action (Sender: TObject; Anforderung: TWebRequest; Antwort: TWebResponse; var
Behandelt: Boolean);
var
PlaintextStream: TStream;
CompressedStream: TStream;
beginnen
if (ClientAcceptsDeflate (Anfrage)) dann
beginnen
// 1. Erstellen Sie zunächst temporären Streams mit zurückzugebenden Daten
PlaintextStream: = TStringStream.Create ('dieser Text ist komprimiert');
versuchen Sie
// 2. Zweitens erstellen Sie temporärer Stream für unsere komprimierten Daten
CompressedStream: = TMemoryStream.Create;
versuchen Sie
// 3. Jetzt komprimieren Sie den Stream...
zLibCompressStream (PlaintextStream, CompressedStream);

... und wieder
CompressedStream.Position: = 0;
Response.ContentStream: = CompressedStream;
mit Ausnahme von
FreeAndNil (CompressedStream);
erhöhen;
end; / / try - außer Speicherverluste zu vermeiden
Schließlich
// 4. Temporäres Objekt endlich Aufräumen
FreeAndNil (PlaintextStream);
end; schließlich versuchen - nur-Text-Stream-Objekt zu zerstören
Response.ContentType: = ' Text/Plain';
Response.ContentEncoding: = 'verkleinern';
Response.StatusCode: = 200;
Behandelt: = True;
Ende / / Wenn Client komprimierte Daten akzeptiert
sonst beginnen
Response.Content: = 'Nicht komprimiert';
Response.ContentType: = ' Text/Plain';
Response.StatusCode: = 200;
Behandelt: = True;
end; / / Wenn Client nicht komprimierte Daten akzeptiert
end; / / Verfahren TWebModule1.WebModule1ActionItem1Action

Hier die primäre If-Anweisung bestimmt, ob der Client verträgt die komprimierten Daten und sendet dann entweder komprimiert oder unkomprimiert Daten zurück an den Client entsprechend. Die unkomprimierten Daten werden behandelt, wie Sie Daten in einer Webanwendung immer behandelt haben, so dass wir, die wird nicht weiter diskutieren. Stattdessen werden wir auf der wenn-dann-Teil der If-Anweisung zu konzentrieren, die komprimierte Daten behandelt. Sie bemerkt wahrscheinlich, dass wir zwei neue Prozeduren/Funktionen hier, nämlich ClientAcceptsDeflate und zLibCompressStream verwenden. Ich gehe durch die weiter unten in diesem Artikel.

Angenommen, wir haben eine Prozedur, die einen Stream als Eingang, komprimiert die Daten annimmt, die diesen Stream hält und schreibt die komprimierten Daten in einen Stream als Ausgang, können wir den Code oben gezeigt wird, wie folgt beschreiben:

  1. Erstellen Sie zunächst einen temporären Streams enthalten, was wir an den Client zurückgeben möchten
  2. Zweitens, komprimieren Sie diese Daten zu und setzen Sie die komprimierten Daten in einen neuen stream
  3. Diese neuen Stream, halten unsere komprimierten Daten, wir geben einfach zurück an den client
  4. Schließlich Aufräumen wir unserer temporäre Objekte

Die übereinstimmende Punkte dieser Liste finden Sie in den nummerierten Kommentaren in den oben genannten Ereignishandler. Es ist ziemlich einfach Code, und sollte auch da haben wir versteckt, die blutigen Details in zwei Funktionen, die wir weiter diskutieren.

Zu bemerken ist, dass sobald wir unseren Stream die ContentStream-Eigenschaft des Response-Objekts zuweisen das Antwort--Objekt Eigentümer des Streams wird. Nachdem die Antwortdaten an den Client Stream gesendet wurde für uns freigegeben wird, so dass wir sicherstellen müssen wir nicht versehentlich es uns befreien. Im Falle einer Ausnahme aber ich davon aus, dass die Zuordnung drunter und drüber ging und somit den Stream vor propagieren die Ausnahme, die weiter oben freizugeben.

Parlez-Vous Français? Um festzustellen, ob der Client weiß, wie komprimierte Daten zu behandeln, die wir einen Blick auf die Daten müssen, sendet er uns an erster Stelle. Eine typische Webanforderung sieht diese (gefälschte Anfrage, so dass die Informationen möglicherweise nicht 100 % richtig):

/ Index.html HTTP/1.0 erhalten
Akzeptieren-Typen: * / *
Accept-Encoding: Gzip, deflate
Benutzer-Agent: Mozilla 4.0 (Microsoft Internet Explorer 5.0 Compatible; NT)

Was wir interessiert, ist die Linie, die geht Accept-Encoding: Gzip, deflate. Es sagt uns, welche Kodierung des Clients akzeptieren kann, und in diesem Fall im Gzip-Format sowie das Deflate-Format codierte Daten annehmen kann. Letzteres ist der, den wir wir also sehen brauchen, wie Sie dieses Wissen aus innerhalb unserer Web-Anwendung zu erhalten. Die Funktion sieht wie folgt aus:

Die Funktion müssen wir schreiben sieht wie folgt aus:

Funktion ClientAcceptsDeflate ( const Anforderung: TWebRequest): Boolean;
var
EncodingTypes: String;
beginnen
Erhalten Sie und neu formatieren Sie Liste Codierungstypen aus der Anforderung
EncodingTypes: = Request.GetFieldByName ('HTTP_HOST');
EncodingTypes: = UpperCase (StringReplace (EncodingTypes, ',', '/', [RfReplaceAll]));
EncodingTypes: = '/' + StringReplace (EncodingTypes, ' ', '', [RfReplaceAll]) + '/';

Rückkehr der Flagge
Ergebnis: = (Pos ('/ entlüften /', EncodingTypes) > 0);
Ende; / / Funktion ClientAcceptsDeflate

Kurz ich die Werte Gzip, deflate in /GZIP/DEFLATE/formatieren und dann überprüfen Sie, ob die Zeichenfolge /DEFLATE/ in ihm gefunden wird. Bist du interessiert zu wissen, sendet welche anderen Feldern in der Anforderung gefunden werden können, dann schlage ich vor, Sie werfen Sie einen Blick auf https://msdn.microsoft.com/library/psdk/iisref/isre504l.htm und verwenden Sie die ALL_HTTP-Variable, welche Variablen überprüfen den Client tatsächlich.

Naturellement, Parlons! Nachdem wir festgestellt haben, dass der Client tatsächlich alle komprimierte Daten verarbeiten kann, was, die wir haben, ist Links zu tun eigentlich die komprimierten Daten zu produzieren und die Magie kommt.

Wie bereits erwähnt, verwenden wir die zLib Kompressionsbibliothek um zu tun, die eigentlich komprimieren. Der Code umfasst folgende Schritte:

  1. Puffer für die Einspeisung von Daten an das Modul eingerichtet sowie komprimierte Daten daraus zu akzeptieren
  2. Kompressionsengine initialisieren
  3. Nur-Text-Daten in den Eingabepuffer aus dem Eingabestream einfließen
  4. Komprimieren des Eingabepuffers in den Ausgabepuffer
  5. Schreiben von Daten aus den Ausgabepuffer in den Ausgabestream geschrieben
  6. Wiederholen Sie Schritte 3 bis 5, bis keine Daten mehr im Eingabestream und Puffer geleert haben
  7. Enge Kompressionsengine

Wir graben in die Details und sehen, was wir zu bewältigen haben:

Procedure zLibCompressStream ( const Quelle, Ziel: TStream);
var
Z_s: Z_stream;
RC: Integer;
// 1. Puffer für ein- und Ausgabe
SourceBuffer: Array[0..BufferSize-1] von Byte;
DestinationBuffer: Array[0..BufferSize-1] von Byte;
beginnen
// 2. Vorbereiten des zLib-Datensatzes
Z_init_zstream (Z_s);
z_s.next_in: = die @SourceBuffer;
z_s.next_out: = die @DestinationBuffer;
z_s.avail_out: = BufferSize;

// 2. Kompressionsengine initialisieren
deflateInit2 (Z_s, Z_BEST_COMPRESSION, Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY);

Jetzt komprimieren Sie den stream
versuchen Sie
Wiederholen Sie die
// 3. Sehen Sie, wenn wir weitere Daten zum Motor Kompression zu füttern
if (z_s.avail_in = 0) und (Source.Position < Source.Size) dann
beginnen
z_s.next_in: = die @SourceBuffer;
z_s.avail_in: = Source.Read (SourceBuffer, Buffersize);
end; / / Wenn Eingabedaten völlig erschöpft

// 4. Komprimierung der Daten
if (z_s.avail_in = 0) dann
RC: = entlüften (Z_s, Z_FINISH)
sonst
RC: = entlüften (Z_s, Z_STREAM_END);

// 5. Prüfen Sie, ob wir komprimierte Daten schreiben zum Ziel haben
if (z_s.avail_out = 0) or (rc = Z_STREAM_END) dann
beginnen
Destination.WriteBuffer (DestinationBuffer, BufferSize - z_s.avail_out);
z_s.avail_out: = BufferSize;
z_s.next_out: = die @DestinationBuffer;
end; / / Wenn die verfügbaren Daten zum Schreiben bekam

// 6. Wiederholen Sie, bis die Puffer leer
bis (Rc-<>-Z_OK) or ((rc = Z_STREAM_END) und (z_s.avail_out = BufferSize) und (z_s.avail_in = 0));
Schließlich
// 7. Die Motordaten bereinigen
DeflateEnd (Z_s);
end; / / versuchen schließlich - nach Motor Aufräumen
end; / / Verfahren zLibCompressStream

Als können vor, Sie die Punkte aus dieser Liste mit den nummerierten Kommentaren oben entsprechen. Der Grund, wir können nicht die zLib zu codieren, die? s mit Delphi enthalten ist, dass es die deflateInit2-Routine und die erforderlichen Parameter im Implementierungsteil des Referats auch nicht den erforderlichen Code offenlegen verbirgt.

Um komprimierte Daten zu erzeugen, die der Browser behandeln kann, müssen wir die Daten mit keine Kopfzeilen-Datensatz zu komprimieren. Im Header-Eintrag ist ein kleiner Datensatz, wird zu Beginn des komprimierten Daten geschrieben und hilft die Dekompression-Engine, die wissen, wie viel Daten, die folgt. Wir können entscheiden, um diese Kopfzeilen-Datensatz nicht zu schreiben, indem Sie einen negativen Wert für den wBitSize-Parameter an die deflateInit2-Prozedur übergeben. Da die Deflate-Standard, der den Browser an, halten erwartet nicht, noch weiß, wie man diesen Header zu behandeln, müssen wir es herausfiltern. Da wir nicht direkt mit dem zLib-Code deflateInit2 nennen könnte, die mit Delphi kam mussten wir auf eine vollständige Dll Kopie die Kompressionsbibliothek zurückgreifen.

Die Kompression-Engine kann der Komprimierung der Daten aus dem Eingabepuffer und in Ausgabepuffer schreiben. Wenn der Ausgabepuffer voll ist, unser Code muss diesen Puffer spülen und schreiben die Daten darin zum Ziel, in unserem Fall einen Stream. Wenn es gelungen ist, alle Daten aus den Eingabepuffer zu komprimieren, muss unser Code, um den Puffer wieder mit so viele Daten wie möglich zu füllen. Kompressionsengine übernimmt den Rest.

Testen Sie ItAfter Ihre Webanwendung kompilieren (siehe unten Artikel für eine Kopie des Projektes Beispiel in diesem Artikel implementiert) Sie sollten idealerweise durch Tests mit beiden einen Browser, der komprimierte Daten verarbeitet und eine, die nicht. Sie können Internet Explorer 4/5 als erstere und Netscape 4.06 als letztere. Die Browser, die Kompression behandelt sollte zeigen den Text 'dieser Text wird komprimiert' und eine 'nicht komprimiert' zur Überprüfung.

Durchschnittliche Komprimierungsverhältnis auf textbasierte Inhalte ist ca. 5 - 6 mal (15-20 % der ursprünglichen Größe) so die Wirkung sollte auf großen Webseiten deutlich bemerkbar.

Wickeln es upWell, das war's. Mit dem Code und in diesem Artikel enthaltene wissen sollten Sie nun komprimierte Daten aus Ihrer Webanwendung behandeln. Obwohl wir in diesem Artikel eine ISAPI-Dll erstellt, sollte die Theorie und den Code auch für CGI und NSAPI Anwendungen unverändert.

Ich habe die Freiheit eine Einheit mit den beiden oben beschriebenen Funktionen sowie eine Kopie des im Beispiel in diesem Artikel produziert erstellt genommen. Sie können die Dateien aus der Liste unten herunterladen. Wenn es irgendwelche Vorschläge oder Dinge, die Sie würde gerne kommentieren, ich unter [email protected] erreicht werden können.

Dateien zum Download:

  • zLib-Dll (von Autoren-Website)
  • Import-Einheit für zLib.dll
  • Beispiel-Projekt (einschließlich Einheit mit zwei Funktionen sowie Import-Gerät)
  • Nur das Gerät mit zwei Funktionen, die wir schrieben

Es gibt ein paar Veredelung Hinweise zu beachten:

  • Kompressionsengine bestimmt nicht, ob die Daten sich leicht, eignet Kompression oder nicht, bevor es beginnt, darauf kauen. Dadurch ist es möglich, Daten über sie zu ernähren, die nicht komprimiert werden und noch verstärken könnte Größe statt. Für Texte und Webseiten ist kein Problem allerdings, aber würde ich einige Tests vor der Fütterung von Jpegs oder Gifs hinein.
  • Die Komprimierung erfolgt serverseitig, bevor es gesendet wird, sodass Wenn der Client versucht, eine sehr große Webseite herunterzuladen dann im Wesentlichen die Webanwendung die gesamte Seite in den Arbeitsspeicher lädt, sie komprimiert und sie sendet. Wenn Speicherverbrauch auf der Serverseite ein Problem ist würde dann ich vorschlagen, Implementierung des Kompression-Codes in eine TStream abgeleitete Klasse, die komprimiert, wenn Sie daraus lesen. Dieser Weg-Komprimierung erfolgt on-the-Fly, wie die Daten gesendet und an dem Client direkt abseits der Plattenoberfläche durch die Kompressionsbibliothek gefüttert werden können. Klassen für auf diese Weise stehen auf meiner Homepage in das Paket namens StreamFilter.


Den Internet-Zug fahren

Den Internet-Zug fahren : Mehreren tausend Tipps, um Ihr Leben einfacher machen.
Den Internet-Zug fahren
Wiezutun
Freunden empfehlen
  • gplus
  • pinterest

Kommentar

Einen Kommentar hinterlassen

Wertung