Rozdział 18. Delphi a Internet
Adam Boduch
Tak, tak, o Internecie była mowa już w rozdziale 11., lecz wówczas podjąłem jedynie temat programowania sieciowego z użyciem różnych protokołów internetowych. Tym razem sprawa wygląda nieco inaczej, bowiem mowa będzie o internetowych zastosowaniach Delphi.
W dziedzinie informatyki postęp jest nieunikniony. Powstają nowe usługi, a języki programowania wciąż są rozwijane. Firma Borland postanowiła udoskonalić swój produkt w zakresie internetowych zastosowań, umożliwiając użytkownikom tworzenie programów działających w sieci Internet, tzw. weplikacji (zlepek słów Web Application). Tworzenie aplikacji internetowych nie jest nowością wprowadzoną dopiero w Delphi 7, istniało już w poprzednich wersjach tego produktu. Owe technologie umożliwiają tworzenie dynamicznych stron WWW, nie wymagając od użytkownika znajomości języka HTML, nie mówiąc już o językach programowania takich jak PHP, CGI, Java czy JavaScript.
1 Z czego będziemy korzystali?
1.1 Serwer Personal Web Server
2 CGI, ISAPI, NSAPI
3 Tworzenie rozszerzeń serwera
4 Akcje serwera
5 Uruchamianie biblioteki
6 Kod źródłowy biblioteki ISAPI
7 TWebRequest i TWebResponse
8 Wykorzystanie szablonów
8.2 Tworzenie nowego szablonu
8.3 Szablony dynamiczne
8.3.1 Zdarzenie OnHTMLTag
8.4 Przykładowy program
9 Witaj!
9.5 Dodatkowe parametry
10 Wysyłanie i odbieranie cookies
10.6 Ustawianie pliku cookies
10.7 Odczyt cookies
11 Wysyłanie strumieni
12 Korzystanie z baz danych
13 WebSnap
14 Podsumowanie
W tym rozdziale:
*poznasz znaczenie terminów ISAPI, NSAPI i CGI;
*dowiesz się, w jaki sposób można tworzyć dynamiczne serwisy WWW;
*nasze przykłady będą opierać się o tworzenie aplikacji z wykorzystaniem technologii ISAPI.
Z czego będziemy korzystali?
Do zrealizowania niektórzy zadań będziemy potrzebować serwera WWW obsługującego standard ISAPI . Co prawda niektóre technologie w Delphi udostępniają własny serwer na potrzeby działania aplikacji, lecz chcąc zaprezentować w pełni działanie programów, będę potrzebował prawdziwego serwera. Ze względu na łatwość obsługi i dostępność na potrzeby tego rozdziału wybrałem serwer firmy Microsoft Personal Web Server, ale Ty możesz skorzystać z dowolnego serwera obsługującego standard ISAPI np. IIS lub Apache.
Serwer Personal Web Server
Program Personal Web Serwer (PWS) jest dostarczany wraz z systemem operacyjnym Windows. W moim przypadku (Windows 98) jest dostępny na płycie CD-ROM w katalogu add-one. Jego instalacja jest prosta - wystarczy postępować zgodnie ze wskazówkami wyświetlanymi na ekranie. Po instalacji na pulpicie zostanie utworzony skrót do owego serwera, a na dysku C: katalog Inetpub.
Program w trakcie działania przedstawiony jest na rysunku 18.1.
Rysunek 18.1. Program Personal Web Server
Właściwe uruchomienie serwera nastąpi po naciśnięciu przycisku Uruchom. Od tego momentu po wpisaniu w przeglądarce internetowej adresu http://127.0.0.1 wczytana zostanie strona z naszego serwera.
Program Personal Web Server można także pobrać z Internetu ? wystarczy skorzystać z jakieś popularnej wyszukiwarki, np. www.google.pl.
CGI, ISAPI, NSAPI
Świat Internetu jest pełen niezrozumiałych pojęć, jak chociażby CGI czy ISAPI. Za chwilę postaram się objaśnić, o co właściwie w tym wszystkim chodzi.
Kiedy powstał Internet, a wraz z nim strony WWW, ich wyświetlanie ograniczało się jedynie do statycznej prezentacji obrazu lub tekstu (czyli stron zapisanych w języku HTML ? ang. HyperText Markup Language). Z czasem, wobec wciąż powiększającej się ?pajęczyny? stron WWW, statyczne strony przestały wystarczać. Serwisy stawały się coraz bardziej rozbudowane, a każda np. grafika wymagała dokonania modyfikacji w każdej podstronie. Zaczęto szukać rozwiązania polegającego na tworzeniu dynamicznych stron WWW, czyli takich, których wygląd zależy od określonej czynności. Pierwszą specyfikacją tego typu było CGI (ang. Common Gataway Interface), które umożliwiało zapisywanie specjalnych skryptów (programów CGI), które generowały dynamiczne strony WWW. Obecnie skrypty CGI są pisanie przeważnie w języku Perl, który jest zwykłym językiem programowania ? dzięki niemu można w łatwy sposób stworzyć księgę gości, system nowości oraz inne elementy interaktywnych stron WWW.
W tamtym okresie na rynku serwerów WWW dominowały dwie firmy ? Microsoft oraz Netscape. Obie doceniły znaczenie tworzenia dynamicznych stron WWW i utworzyły podobne do siebie standardy ? ISAPI (Microsoft) oraz NSAPI (Netscape). Zarówno ISAPI, jak i NSAPI to w rzeczywistości biblioteki DLL, umożliwiające dynamiczne generowanie stron internetowych; nazywane są często rozszerzeniami serwerów WWW. Większą popularność zyskała technologia ISAPI i to przede wszystkim nią zajmiemy się w tym rozdziale. Jednak ISAPI potrzebuje do działania serwera WWW ? stąd potrzebny nam był chociażby najprostszy serwer, jakim jest Personal Web Server.
Obecnie dominującą technologią tworzenia stron WWW jest PHP, lecz niektóre firmy (rzadziej prywatne osoby) wciąż stosują ISAPI w celu zaprojektowania dynamicznych stron i dlatego zajmiemy się teraz ich tworzeniem.
W tym miejscu należy się jeszcze jedna, mała uwaga. W momencie wpisania w przeglądarce np. adresu http://127.0.0.1/SCRIPTS/ISAPI.dll załadowana zostanie biblioteka DLL, która (niestety) będzie przebywać w przestrzeni adresowej serwera aż do jego zamknięcia. Inaczej mówiąc, Windows nie pozwoli na usunięcie takiej biblioteki ani jej zmodyfikowanie przed zakończeniem pracy serwera. To rozwiązanie ma jednak zalety w postaci większej wydajności, w przeciwieństwie do programów CGI, które muszą być uruchamiane za każdym wywołaniem.
Nie wszystkie serwery stosują takie praktyki ? w niektórych istnieje możliwość podmiany pliku w trakcie działania serwera.
Tworzenie rozszerzeń serwera
Tworzenie biblioteki ISAPI zaczynamy jak zwykle w Repozytorium (rysunek 18.2). Po zaznaczeniu ikony Web Server Application i kliknięciu OK Delphi otworzy okno, w którym będziemy musieli wybrać rodzaj rozszerzenia serwera WWW ? patrz rysunek 18.3.
Rysunek 18.2. Repozytorium z zaznaczoną ikoną Web Server Application
Rysunek 18.3. Nowa aplikacja serwera
Pierwsze domyślnie zaznaczone pole to projekt biblioteki ISAPI lub NSAPI (tym się zajmiemy); kolejna opcja służy do tworzenia rozszerzenia typu CGI, które przebiega bardzo podobnie. Kolejne dwie pozycje związane są z tworzeniem modułów najpopularniejszego serwera WWW ? Apache. Mamy do wyboru tworzenie modułu do wersji 1.x tego serwera lub do wersji 2.x.
Ostatnia pozycja związana jest z tworzeniem rozszerzenia wykorzystującego specjalny debuger, który stanowi także serwer dla tworzonego projektu.
W poprzednich wersjach Delphi możliwe było także tworzenie aplikacji rozszerzeń Win-CGI (Common Gataway Interface for Windows), lecz obecnie Borland wycofał się z tej strategii, uznając ją za przestarzałą.
Korzystanie z ISAPI (Internet Server API) jest możliwe jedynie na platformie Windows.
Po wybraniu typu rozszerzenia Delphi utworzy formularz oparty o klasę TWebModule
, która stanowi jedynie ?pojemnik? na umieszczane komponenty. W rzeczywistości nie pozwala na umieszczanie komponentów wizualnych, gdyż nie ma to w tym wypadku najmniejszego sensu. Jedyne komponenty mogące znaleźć się na formularzu to komponenty niewidoczne ? w szczególności komponenty z zakładki Internet oraz komponenty do obsługi baz danych.
Akcje serwera
Klasa TWebModule
implementuje system obsługi protokołu HTTP, jednak wykorzystanie ISAPI opiera się na tzw. akcjach, w ramach których program wykonuje pewne zadania. Sama ?akcja? dołączana jest do adresu w przeglądarce ? np.:
http://127.0.0.1/isapi.dll/test
W tym wypadku akcję stanowi fragment /test.
Tworzenie akcji odbywa się poprzez właściwość Action
klasy TWebModule
(rysunek 18.4).
Rysunek 18.4. Edytowanie akcji modułu aplikacji
Całość odbywa się za pośrednictwem okna WebModule.Actions
(rysunek 18.4). Okno to podzielone jest na poszczególne kolumny: PathInfo
jest właśnie fragmentem wstawianym na koniec adresu i identyfikującym daną akcję. Pierwsza kolumna ? Name ? określa nazwę.
Utworzenie nowej akcji odbywa się poprzez naciśnięcie pierwszego przycisku z lewej lub naciśnięciu klawisza Insert. Kod źródłowy, który ma zostać wykonany w wyniku wywołania takiego adresu, generowany jest za pośrednictwem zdarzenia OnAction
:
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
end;
Informacja zwrotna musi zostać zawarta w parametrze Response
typu TWebResponse
. W parametrze k zawarte są informacje na temat żądania HTTP, co niesie ze sobą ciekawe informacje, jak nazwa protokołu i inne nagłówki HTTP. W naszym przykładzie kod całego modułu prezentuje się tak, jak w listingu 18.1.
Listing 18.1. Kod źródłowy modułu
unit MainFrm;
interface
uses
SysUtils, Classes, HTTPApp;
type
TWebModule1 = class(TWebModule)
procedure WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule1: TWebModule1;
implementation
{$R *.dfm}
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
HTML : String;
begin
HTML := '<html>' +
'<head>' +
'<title>Przykład wykorzystania ISAPI</title>' +
'</head>'+
'<body>'+
'<h1>Witaj, użytkowniku!</h1>'+
'<hr>'+
'<i>Copyright (c) 2003 by Adam Boduch</i>'+
'</body>'+
'</html>';
Response.Content := HTML;
end;
end.
Na samym początku następuje formułowanie zawartości strony WWW zwracanej w wyniku wywołania biblioteki. Kod HTML przypisywany jest do zmiennej HTML; zwracanie zawartości tej zmiennej następuje w momencie przypisania jej do właściwości Content
parametru Response
.
Uruchamianie biblioteki
Jako że nasza biblioteka nie może działać samodzielnie, należy umieścić ją w odpowiednim katalogu serwera. Zbuduj więc bibliotekę (Project/Build), w wyniku czego w katalogu z projektem utworzony zostanie plik Isapi1.dll (w moim przypadku). Ów plik należy umieścić gdzieś w katalogu serwera ? niech będzie to C:\Inetpub\scripts. Następnie uruchom przeglądarkę WWW i wpisz następujący adres: http://127.0.0.1/scripts/isapi1.dll/default.
Rezultat działania takiej biblioteki przedstawiony jest na rysunku 18.5.
Rysunek 18.5. Rezultat działania biblioteki ISAPI
Nie zapominaj o ?doklejeniu? na końcu adresu WWW fragmentu /default.
Kod źródłowy biblioteki ISAPI
Spójrz na kod źródłowy głównego projektu *.dpr biblioteki (Project/View Source):
library isapi1;
uses
ActiveX,
ComObj,
WebBroker,
ISAPIThreadPool,
ISAPIApp,
MainFrm in 'MainFrm.pas' {WebModule1: TWebModule};
{$R *.res}
exports
GetExtensionVersion,
HttpExtensionProc,
TerminateExtension;
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
Application.CreateForm(TWebModule1, WebModule1);
Application.Run;
end.
Na pierwszy rzut oka główny plik *.dpr jest bardzo podobny do głównego pliku zwykłej aplikacji VCL. Zwróć uwagę na trzy procedury eksportowane przez naszą bibliotekę (GetExtensionVersion
, HttpExtensionProc
, TerminateExtension
). Pierwsza z nich zwraca serwerowi numer wersji rozszerzenia; kolejne polecenie eksportuje rozszerzenia związane z obsługą protokołu HTTP. Ostatnia procedura jest związana z prawidłową obsługą procesu zakończenia działania programu i zwolnienia biblioteki.
TWebRequest i TWebResponse
Obie klasy organizują komunikację pomiędzy serwerem WWW a rozszerzeniem, czyli biblioteką DLL. W parametrze Request znajdują się żądania klienta, czyli także nagłówki HTTP, natomiast Response określa zwracane przez bibliotekę wartości.
Klasa TWebRequest
, a konkretnie jej właściwości, dostarczają wielu ciekawych informacji na temat naszego rozszerzenia oraz na temat użytkownika ? np. dane o przeglądarce (nazwa i wersja), systemie operacyjnym, metodzie wywołania strony, adresie itp. Najciekawsze informacje zgromadziłem w tabeli 18.1.
Tabela 18.1. Właściwości klasy TWebRequest
Nazwa | Opis |
---|---|
`Method` | Metoda wywołania strony (GET, POST) |
`ProtocolVersion` | Wersja protokołu HTTP |
`UserAgent` | Używana przeglądarka |
`URL` | Adres wywoływanego programu w katalogu serwera |
`ServerPort` | Numer portu serwera |
`ScriptName` | Nazwa wywoływanego skryptu (np. /skrpty/isapi.dll) |
`RemoteAddr` | Adres IP użytkownika korzystającego z programu |
`RemoteHost` | Nazwa hosta użytkownika (np. ppp.tpnet.pl). |
`Referer` | Strona, z której użytkownik trafił na nasz program |
`Query` | Dodatkowe parametry przekazane wraz z programem (np. imie=adam&nazwisko=boduch) |
`QueryFields` | Rozdzielone już parametry, dołączane do programu (w postaci typu `TStringList`) |
`PathInfo` | Człon określający akcje do wykonania, np. w przypadku adresu http://127.0.0.1/default.dll/get właściwość zwróci /get |
`Host` | Host, czyli adres strony ? np. http://127.0.0.1 |
`ContentLength` | Długość nagłówka HTTP |
`ContentEncoding` | Mechanizm kodowania nagłówka |
`ContentFields` | Zawiera parametry przekazane metodą POST do skryptu |
Teraz przykład prezentujący korzystanie z tej wiedzy w praktyce ? oto, jak może wyglądać zdarzenie OnAction
:
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
HTML : TStringList;
begin
{ konstruowanie treści zwracanej przez program }
HTML := TStringList.Create;
try
HTML.Add('<html>');
HTML.Add('<head>');
HTML.Add('<title>Informacje dotyczące HTTP</title>');
HTML.Add('</head>');
HTML.Add('<body>');
HTML.Add('<h1>HTTP</h1>');
HTML.Add('Metoda: <b>' + Request.Method + '</b><br>');
HTML.Add('URL: <b>' + Request.URL + '</b><br>');
HTML.Add('Przeglądarka: <b>' + Request.UserAgent + '</b><br>');
HTML.Add('</body>');
HTML.Add('</html>');
Response.Content := HTML.Text;
finally
HTML.Free;
end;
Handled := True;
end;
Do skonstruowania strony HTML użyłem typu TStringList
, gdyż jest to chyba najprostszy sposób, lepszy niż łączenie wszystkiego w jeden długi łańcuch String. Ze względu na długość kodu w przykładzie (rysunek 18.6) zaprezentowałem wykorzystanie jedynie trzech właściwości, lecz Ty ? jeżeli chcesz ? możesz napisać kod wyświetlający większą ilość danych.
Rysunek 18.6. Przykład wykorzystania danych z nagłówka HTTP
Wykorzystanie szablonów
Takie wpisywanie treści strony bezpośrednio w kodzie źródłowym programu może być trochę niepraktyczne. Można jednak ten problem ominąć, wykorzystując element szablonów. Polega to, ogólnie mówiąc, na oddzieleniu rzeczywistego kodu programu od treści HTML, która ma być wynikiem działania skryptu.
Funkcje taką umożliwia komponent TPageProducer
, mieszczący się w zakładce Internet. Aby z niego skorzystać, należy podczas tworzenia akcji rozwinąć w Inspektorze Obiektów właściwość Producer
i wybrać komponent typu TPageProducer
(rysunek 18.7).
Rysunek 18.7. Właściwość Producer
Od tej pory przy każdorazowym wywołaniu tej akcji wyświetlony zostanie kod z właściwości HTMLDoc komponentu TPageProducer
.
Tworzenie nowego szablonu
Aby nasz szablon w ogóle zadziałał, konieczne jest wpisanie jakiejś treści HTML we właściwości HTMLDoc ? np. takiej:
<html>
<head>
<title>Strona generowana z użyciem komponentu TPageProducer</title>
</head>
<body>
Witam! Oto przykładowa strona generowana z użyciem szablonów!
</body>
</html>
Właściwość HTMLDoc jest typu TStrings
, więc jej edycja może nastąpić zarówno z poziomu programu, jak i podczas jego projektowania (rysunek 18.8).
Rysunek 18.8. Edycja właściwości HTMLDoc
Właściwie nie jest konieczne wpisywanie żadnego kodu ? nasz program jest już gotowy do kompilacji i uruchomienia.
Zamiast właściwości HTMLDoc można zastosować także właściwość HTMLFile. Wówczas treść strony HTML będzie odczytywana z pliku.
Szablony dynamiczne
Rozszerzenia serwerów są w końcu używane po to, aby umożliwić użytkownikowi generowanie dynamicznych stron w zależności od określonego zdarzenia. Szablony w pewien sposób uniemożliwiają zachowanie dynamiczności, gdyż zawartość dokumentu ? odczytywana z właściwości HTMLDoc ? jest stała.
Problem ten można częściowo rozwiązać, stosując specjalnie znaczniki w treści kodu HTML. Wówczas możemy w trakcie programu zmieniać zawartość owych znaczników wedle własnego uznania.
Przykładowo jeżeli w treści strony HTML znajduje się znacznik <#your_name>
, to zastąpienie tego znacznika określoną treścią ogranicza się jedynie do wywołania metody OnHTMLTag
komponentu TPageProducer
:
procedure TWebModule1.HTMLPageHTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings; var ReplaceText: String);
begin
if Tag = tgCustom then
begin
if TagString = 'your_name' then ReplaceText := strName
else if TagString = 'country' then ReplaceText := strCountry;
end;
end;
Ważna jest jednak specjalna konstrukcja znaczników HTML ? muszą być zawarte w nawiasach < i >, a pierwszym znakiem nazwy znacznika musi być #. Wówczas komponent analizuje treść HTML z właściwości HTMLDoc i przy każdorazowym napotkaniu znacznika wywołuje zdarzenie OnHTMLTag
.
Zdarzenie OnHTMLTag
Znaczenie poszczególnych parametrów zdarzenia OnHTMLTag
jest następujące:
*Tag
? wskazanie na typ TTag
, który identyfikuje rodzaj znacznika (patrz tabela 18.2).
*TagString
? łańcuch (String) identyfikujący określony znacznik. Nazwa znacznika jest pozbawiona początkowych znaków <# oraz >.
*TagParams
? dodatkowe parametry znacznika. Do określonego znacznika mogą być dołączone określone parametry, ale o tym powiem za chwilę.
*ReplaceText
? tekst, który ma zastąpić identyfikowany znacznik.
Tabela 18.2. Znaczenie poszczególnych pozycji typu TTag
Parametr | Opis |
---|---|
`tgLink` | Odnośnik do innej strony WWW w postaci `<#LINK Dest=adres_www>`. Inaczej mówiąc, jest to znacznik ` ` zapisany w HTML |
` z HTML</td></tr>
`tgTable`</td>Tabela ? inaczej znacznik `
` w HTML. Budowa znacznika: `<#TABLE Param1=warość>`</td></tr>
`tgImageMap`</td>Mapa obrazka ? inaczej znacznik `<map>` z HTML. Budowa: `<#IMAGEMAP Param1=wartość>`</td></tr>
`tgObject`</td>Inaczej znacznik `<object>`, identyfikujący wstawiany obiekt ? np. kontrolkę ActiveX. Budowa: `<#OBJECT Control=adres_do_konstrolki>`</td></tr>
`tgCustom`</td>Nieokreślony znacznik</td></tr>
</tbody>
</table>
...
if TagString = 'your_name' then ReplaceText := strName;
...
Przykładowy program
Listing 18.2. Kod źródłowy przykładowej strony WWW
<html>
<head>
<title>Podaj swoje imię</title>
</head>
<body>
Witaj!
Proszę wpisać w poniższym formularzu swoje imię i miejsce zamieszkania
<form action="templates2.dll/get" method="GET">
Imię: <input type="text" name="your_name">
Kraj: <input type="text" name="your_country">
<input type="Submit" value="Wyślij">
</form>
</body>
</html>
```
Rysunek 18.9. Formularz strony WWW
Request.QueryFields.Values['your_name'];
Listing 18.3. Kod źródłowy programu
unit MainFrm;
interface
uses
SysUtils, Classes, HTTPApp, HTTPProd;
type
TWebModule1 = class(TWebModule)
HTMLPage: TPageProducer;
procedure WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
procedure HTMLPageHTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings;
var ReplaceText: String);
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule1: TWebModule1;
implementation
{$R *.dfm}
var
strName, strCountry : String;
procedure TWebModule1.WebModuleBeforeDispatch(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
strName := Request.QueryFields.Values['your_name'];
strCountry := Request.QueryFields.Values['your_country'];
end;
procedure TWebModule1.HTMLPageHTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings; var ReplaceText: String);
begin
if Tag = tgCustom then
begin
if TagString = 'your_name' then ReplaceText := strName
else if TagString = 'country' then ReplaceText := strCountry;
end;
end;
end.
Rysunek 18.10. Działanie biblioteki
Dodatkowe parametry
<html>
<head>
<title>Strona generowana z użyciem komponentu TPageProducer</title>
</head>
<body>
<#IMAGE ID=helion>
</body>
</html>
```
Oto przykład, jak może wyglądać zdarzenie
OnHTMLTag
komponentu TPageProducer
:
procedure TWebModule1.HTMLPageHTMLTag(Sender: TObject; Tag: TTag;
const TagString: String; TagParams: TStrings; var ReplaceText: String);
begin
if Tag = tgImage then
begin
if TagParams.Values['ID'] = 'helion' then
ReplaceText := '<img src=http://127.0.0.1/helion.bmp>';
end;
end;
Wysyłanie i odbieranie cookies
Wysyłanie i odbieranie cookies
Ustawianie pliku cookies
Ustawianie pliku cookies
Plik cookie ustawiany jest za pomocą metody
SetCookieField
z klasy TWebResponse
:
procedure SetCookieField(Values: TStrings; const ADomain, APath: string; AExpires: TDateTime; ASecure: Boolean);
procedure TWebModule1.WebModule1setAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
S : TStringList;
begin
S := TStringList.Create;
try
S.Add('Browser=' + Request.UserAgent); // dodanie informacji o przeglądarce
S.Add('Visit=' + FormatDateTime('dd:mm:yyyy', Now)); // informacja o dacie wizyty
Response.SetCookieField(S, '', '', 17-02-2004, False);
Response.Content := 'Ciasteczko zostało ustawione...';
finally
S.Free;
end;
end;
Odczyt cookies
Odczyt cookies
procedure TWebModule1.WebModule1getAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
begin
Response.Content := 'Byłeś tutaj ' + Request.CookieFields.Values['Visit'] + ' i korzystałeś z ' + Request.CookieFields.Values['Browser'];
end;
Rysunek 18.11. przedstawia program w trakcie działania (odczytywanie cookies).
Rysunek 18.11. Odczytanie pliku cookies
W systemach Windows pliki cookies przechowywane są w katalogu C:\Windows\Cookies (Windows 9.x.).
Wysyłanie strumieni
Wysyłanie strumieni
Response.ContentType := 'image/pjpeg';
procedure TWebModule1.WebModule1sendAction(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
JPG : TResourceStream;
begin
{ załaduj obrazek z rejestru }
JPG := TResourceStream.Create(hInstance, 'PIC', 'JPEGFILE');
try
// typ danych wyjściowych ? obrazek JPEG
Response.ContentType := 'image/pjpeg';
Response.ContentStream := JPG; // wysyłane dane
Response.SendResponse; // wyślij
Handled := True;
finally
JPG.Free;
end;
end;
{$R FILES.res}
Korzystanie z baz danych
Korzystanie z baz danych
Listing 18.4. Kod źródłowy programu korzystającego z baz danych
unit MainFrm;
interface
uses
SysUtils, Classes, HTTPApp, HTTPProd, DB, DBTables;
type
TWebModule1 = class(TWebModule)
Table: TTable;
procedure WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
WebModule1: TWebModule1;
implementation
{$R *.dfm}
procedure TWebModule1.WebModule1WebActionItem1Action(Sender: TObject;
Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
HTML : TStringList;
begin
HTML := TStringList.Create;
try
{ tworzenie początku szablonu }
HTML.Add('<html>');
HTML.Add('<head>');
HTML.Add('<title>Odczyt z baz danych</title>');
HTML.Add('</head>');
HTML.Add('<body>');
HTML.Add('<table width="60%" size="1" border="1">'); // tworzenie tabeli
HTML.Add('<tr><td width="5%">ID</td><td width="60%">Towar</td><td width="15%">Cena</td><td width="20%">Data</td></tr>');
Table.Active := True;
{ kolejne odczytywanie następnych rekordów i dodawanie ich do rezultatu HTML }
while not Table.Eof do
begin
HTML.Add('<tr>');
HTML.Add('<td width="5%">' + IntToStr(Table.FieldValues['id']) + '</td>');
HTML.Add('<td widrh="60%">' + Table.FieldValues['Towar'] + '</td>');
HTML.Add('<td width="15%">' + FloatToStr(Table.FieldValues['Cena']) + '</td>');
HTML.Add('<td width="20%">' + DateTimeToStr(Table.FieldValues['Data']) + '</td>');
HTML.Add('</tr>');
Table.Next;
end;
HTML.Add('</table>');
Table.Active := False;
HTML.Add('</body>');
HTML.Add('</html>');
Response.Content := HTML.Text;
Handled := True;
finally
HTML.Free;
end;
end;
end.
Rysunek 18.12. Odczyt rekordów z bazy danych
WebSnap
WebSnap
Podsumowanie
Podsumowanie
</li>
</ul>
</td>
Więcej informacji
Format: B5, stron: 1048
oprawa twarda
Zawiera CD-ROM
</td>
</tr>
</table>