Публикация баз данных в среде WWW

с помощью инструментальных средств Inprise Corp.

Существует множество подходов для публикации данных в среде World Wide Web. Например: разложить содержимое реляционной базы данных на отдельные файлы и поместить их на Web-сервер, затем организовать поиск с помощью программного обеспечения индексации Web-сервера, но наиболее эффективный из них - это метод, основанный на CGI.


CGI

Служба узла Web предоставляет очень удобные технологии для создания динамических страниц HTML. Одна из них - это CGI (Common Gateway Interface). CGI представляет собой набор спецификаций для обмена информацией между Web-браузером, сервером Web и приложением CGI. Этот путь можно разбить на пять участков.

  1. Клиент посылает запрос одним из следующих методов: GET-данные добавляются в адрес URL и передаются на сервер, POST-данные отправляются на сервер в поле сообщения HTTP (этим методом можно преодолеть ограничения, присущие методу GET). URL, который браузер пересылает серверу, содержит имя выполняемой программы.
  2. Web-сервер передает данные приложению CGI через переменные среды окружения и запускает приложение. Немного о реализации метода POST в сервере WebSite. Сервер разделяет запрос на заголовки и содержимое и помещает эту информацию в переменные сервера. Значение этих переменных помещается во временный INI-файл. Сервер передает полное имя этого файла (включая и путь) в командную строку запуска CGI-приложения.
  3. CGI-приложение (шлюзовое приложение) обращается к SQL-серверу базы данных, получает или передает ему информацию.
  4. Приложение-шлюз возвращает данные Web-серверу. Первая строка ответа должна содержать тип возвращаемого документа. Сервер WebSite сам добавит остальную часть HTTP-заголовка. Для интерфейса WinCGI, реализованного в WebSite, CGI-приложение должно создать файл вывода, воспользовавшись для этого именем, которое сервер поместил в INI-файл.
  5. Web-сервер обрабатывает данные, принятые от CGI-приложения (через поток ввода-вывода, файл), и передает на клиентский компьютер, где они отображаются в браузере.


База данных

База данных может быть создана практически в любой СУБД, главное требование: СУБД должна обладать богатым набором прикладного API для работы с данными и дисковыми файлами. Если предполагается большое количество обращений, лучше остановиться на технологии клиент-сервер. Inprise предлагает неплохую связку InterBase/C++ Builder. InterBase поддерживает стандартный SQL, поэтому создание БД с помощью SQL-скриптов для "InterBase Windows SQL" (ISQL) не вызывает трудностей. Первая строчка скрипта - предложение CREATE DATABASE...; это же действие можно выполнить через меню в ISQL, File | Create Database. При последующих обращениях к БД первая строчка будет CONNECT "база" USER "имя" PASSWORD "пароль". При создании БД кодировку символов лучше установить для всей базы, для этого используется дополнительный параметр DEFAULT CHARACTER SET WIN1251. Если вы создаете БД в ISQL, то эта фраза вписывается в memo-поле Database Options. Еще одно замечание: WIN1251 не имеет таблицы перевода строчных букв в прописные для русского языка. Чтобы в SQL-запросе корректно работала функция UPPER, необходимо при создании текстовых полей, содержащих кириллицу, использовать уточнение (COLLATION SEQUENCE) COLLATE PXW_CYR, например, так: create table people (fio CHAR(50)COLLATE PXW_CYRL). После создания таблиц или прямо в них определяются первичные и вторичный ключи, создаются индексы. IB в явном виде не поддерживает тип "autoincrement", поэтому необходимо использовать пару генератор-триггер. Здесь генератор - переменная, значение которой может быть получено и увеличено на какую-то величину. Триггер срабатывает на событие в БД, в данном примере он помещает значение генератора PEOPLE_GEN в поле people_id таблицы people перед вставкой новой строки.

CREATE GENERATOR PEOPLE_GEN; SET TERM ^;
CREATE TRIGGER PEOPLE_GEN_TR FOR people
ACTIVE BEFORE INSERT POSITION 0
AS BEGIN
NEW.PEOPLE_ID = GEN_ID(PEOPLE_GEN, 1);
END ^
COMMIT WORK ^ SET TERM; ^ EXIT;


Заполнение таблиц

Следующий шаг - создание псевдонима (Alias) для базы данных. Для этого необходимо воспользоваться утилитами "BDE Administrator" или "SQL Explorer". На страничке System для драйвера INTRBASE (чтобы потом не делать то же самое каждый раз при создании нового псевдонима) и для псевдонимов INTRBASE устанавливается параметр LANGUAGE DRIVER = Pdox ANSI Cyrillic. Для заполнения таблиц текстовыми данными можно использовать SQL-команду INSERT, набивать данные непосредственно в "DataBase Desktop" или "SQL Explorer", либо воспользовавшись мастер-визардом и сгенерировав форму ввода непосредственно в C++Builder. Немного сложнее вставить в базу данных BLOB'ы (Binary Large OBject) - фотографии, большие текстовые документы или аудиоматериалы. Для работы с этими объектами в C++ Builder существуют классы TFileStream и TBlobStream. Алгоритм следующий: создаем объекты класса TFileStream и TBlobStream, объект класса TBlobStream связываем с соответствующим полем таблицы, а объект класса TFileStream связываем с файлом, который мы хотим поместить в BLOB поле, в цикле, пока не конец файла, заполняем BLOB поле в таблице. Запись происходит в активную на данный момент строку таблицы. Table2 - это компонента TTable. Перед записью необходимо перевести набор данных в режим редактирования dsEdit, после записи данных вызывается метод TTable - Post().

10 TFileStream *sF = new TFileStream(ФАЙЛ,fmOpenRead);
20 Table2->Edit();
30 if (Table2->State == dsEdit) {
40 TBlobStream *sB = new TBlobStream((TBlobField *)
50 Table2->FieldByName(ПОЛЕ_ТАБЛИЦЫ), bmWrite);
60 do { char Buff[256];
70 int i = sF->Read(Buff, sizeof(Buff));
80 sB->Write(Buff, i);
90 } while(i!= 0);
00 Table2->Post(); };


HTML

В HTML для CGI можно использовать теги <form action...> и <input type="hidden" name="Form" value="Find">. Первый предписывает запустить CGI-приложение и при передаче параметров использовать метод POST или GET. Второй, так называемый скрытый элемент, обеспечивает возможность передачи невидимой пользователю информации для CGI-приложения. Анализируя такую переменную, CGI-приложение будет "знать", какую HTML-страничку ему генерировать. Для передачи изображений используется тег <img src...>. В него помещается URL CGI-программы и она в ответ на запрос обращается к базе, вычитывает рисунок и передает его WebServer'у.


CGI-приложение

Для создании CGI-приложения, которое будет обращаться к базе данных, созданной в IB, удобен C++Builder. Для доступа к БД используется стандартная связка TDatabase и TQuery или TTable. Анализ командной строки в Builder'е проще всего осуществить через две функции - ParamCount() и ParamStr(). ParamCount() - возвращает количество значений. ParamStr() - служит для доступа к конкретной переменной. Рассмотрим последовательность действий, выполняемых CGI-программой:

1. Прочитать из INI-файла, переданного WebSite'ом, необходимые переменные, используя класс TIniFile. Результатом будет строка с именем файла, например: "D:\WebSite\cgi-temp\80ws.000 5". В этом файле лежат данные, которые пользователь ввел в форму. Цифра 5 показывает количество введенных символов.

2. Прочитать из "D:\WebSite\cgi-temp\80ws.000" данные, используя билдеровский класс TFileStream. Законнектиться к IB, выполнить SQL-запрос. При обращении к IB сервер проводит аутентификациюю. Чтобы этого не происходило, можно воспользоваться компонентом TDatabase.

10 Form1->DB1->DatabaseName = "MyDB";
20 Form1->DB1->AliasName = "IB_WORK";
30 Form1->DB1->Params->Values["USER NAME"]="SYSDBA";
40 Form1->DB1->Params->Values["PASSWORD"]= "masterkey";
50 Form1->DB1->LoginPrompt = false;

3. Перенести данные, которые вернул TQuery, в HTML-шаблон. Информацию из BLOB-поля можно вытащить, используя пару TTable и TBlobField. В TBlobField нужен метод SaveToStream. В строчках 50 и 60 позиционируется указатель в наборе данных на нужную нам строку таблицы.

10 TBlobField* blData = new TBlobField(Form1);
20 blData->SetFieldType(ftMemo);
30 blData = (TBlobField*) Form1->Table1->FieldByName("ПОЛЕ");
40 Form1->Table1->SetKey();
50 Form1->Table1->FieldByName("ПОЛЕ")->AsInteger 
60 = Form1->Query1->Fields[ПОЛЕ]->AsInteger;
70 Form1->Table1->GotoKey();
80 blData->SaveToStream(strOut);

Основной цикл работы программы можно построить в обработчике формы FormShow по следующей схеме:

switch(Определение метода вызова CGI){
case это метод GET:
switch (Опр.парам.переданного методом GET){
case это параметр_1: действие_1; break;
case это параметр_2: действие_2; break;
case это рисунок_3: действие_3; break; 
} break;
case это метод POST:
switch (Опр.парам.переданного методом POST){
case это параметр_1: действие_1; break;
case это параметр_2: действие_2; break;
}; break;
}; Close();

В небольшой статье трудно охватить все тонкости спецификации CGI-приложения, за более подробной информацией обращайтесь по адресу www.cgi-resources.com.

Андрей ЛАПОУХОВ,
[email protected]

Версия для печатиВерсия для печати

Номер: 

10 за 1999 год

Рубрика: 

Азбука программирования
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!