Электронная библиотека книг Александра Фролова и Григория Фролова.
 
Библиотека
Братьев
Фроловых
Электронная библиотека книг Александра Фролова и Григория Фролова.
Библиотека системного программиста
Программирование на JAVA
ПК. Шаг за шагом
Другие книги
Восстановление данных
Антивирусная защита
Статьи для
программистов
Пользователю компьютера
[Назад] [Содержание] [Дальше]

Создание Web-приложений: Практическое руководство

© Александр Фролов, Григорий Фролов
М.: Русская Редакция, 2001, 1040 стр.

9. Применение технологии ASP

9. Применение технологии ASP.. 1

Основы ASP. 2

Простейший пример. 2

Пример с циклом.. 4

Обработка формы.. 5

Комбинирование клиентского и серверного сценариев. 7

Приложения ASP и сеансы... 9

Файл global.asa. 9

Переменные приложений ASP.. 11

Практическое применение ASP. 11

Создание мастера средствами ASP.. 11

Подсчет количества активных сеансов. 20

Использование Cookie в сценариях ASP.. 21

Регистрация пользователей. 26

Передача параметров через скрытые поля форм.. 30

Отладка сценариев в страницах ASP. 32

Организация поиска страниц на Вашем узле Web.. 34

Настройка сервиса Indexing Service. 36

Создание служебного каталога. 37

Указание пути индексируемой папки. 38

Подготовка сценария для поиска страниц. 38

Работа с файлами.. 40

Создание объекта FileSystemObject 41

Создание нового файла. 41

Открытие существующего файла. 41

Закрытие файла. 42

Запись в файл. 42

Чтение файла. 44

Позиционирование в файле. 44

Удаление файлов. 44

Копирование файла. 45

Перемещение файла. 45

Проверка существования файла. 45

Обработка ошибок. 45

Использование объекта Dictionary.. 46

Создание объекта Dictionary. 46

Добавление нового элемента. 47

Проверка существования элемента. 47

Получение значения элемента. 47

Изменение элемента. 47

Использование объекта Dictionary для перекодировки. 48

 

Существует два способа создания активного сервера Web на базе Microsoft Internet Information Server — с применением программ расширения CGI или ISAPI либо с помощью активных серверных страниц ASP (возможно также применение технологии PHP, напоминающей ASP).

Первый способ предполагает составление достаточно сложных программ на языке C++ или использование интерпретируемых языков наподобие Perl. Программы расширения сервера Web представляют собой обычные приложения, исполняемые на компьютере сервера Web. Они могут обращаться к базам данных таким же образом, как и обычные автономные приложения.

Главный недостаток этого способа заключается, на наш взгляд, в сложности разработки и отладки программ расширений сервера Web, что значительно замедляет процесс разработки больших и сложных проектов. Особенно тяжело при этом сопровождать проекты, которые постоянно изменяются.

Что же касается активных серверных страниц ASP, то они значительно проще, хотя позволяют решать те же самые задачи, что и программные расширения сервера Web. Страницы ASP представляют собой текстовые файлы с конструкциями языка HTML и сценариями, составленными на таких языках программирования, как JScript и VB Script. Фактически, если Вы уже владеете этими языками программирования, изучение технологии ASP не отнимет у Вас много времени.

Возможность составления серверных приложений с применением высокоуровневых языков сценариев и технологии компонентов COM значительно упрощает создание сложных приложений Web. При этом от разработчика не требуется глубокого понимания тонкостей программирования на уровне интерфейса операционной системы или прикладных интерфейсов базы данных. Все разработки ведутся в терминах интерфейсов и свойств высокоуровневых компонент COM.

Отметим, что сценарии, расположенные в страницах ASP, могут быть серверными и клиентскими. Серверные сценарии выделяются специальным образом и исполняются на сервере, в то время как клиентские сценарии работают на компьютере пользователя под управлением браузера, например Microsoft Internet Explorer.

Результатом работы серверных сценариев ASP является динамически формируемый текст документа HTML, отсылаемый пользователю. Этот текст загружается в окно браузера. Если сформированный документ HTML содержит клиентские сценарии, они будут выполнены браузером.

Основы ASP

Изучать технологию ASP проще всего на конкретных примерах. Придерживаясь методики известных классиков программирования на языке C, мы прежде всего подготовим простейшую страницу ASP, создающую документ HTML с заголовком “Hello, ASP World!”. Заголовок формируется средствами серверного сценария JScript. Затем мы приведем еще несколько примеров, демонстрирующих некоторые возможности технологии ASP.

Простейший пример

Итак, убедитесь, что на Вашем компьютере установлен сервер Internet Information Server версии 4.0 или более новой. Затем создайте каталог с именем, например, BookStore. Средствами управляющей консоли Microsoft Management Console создайте виртуальный каталог, отображенный на каталог BookStore, и разрешите чтение, а также исполнение сценариев. Для этого в панели BookStore Properties (рис. 9-1) откройте вкладку Virtual Directory и пометьте переключатели Read и Script (если они были сброшены).

Рис. 9-1. Настройка доступа к виртуальному каталогу BookStory

Переключатель Run in separate memory space (isolated process) позволяет запускать все приложения, относящиеся к данному каталогу, в отдельном адресном пространстве. Несмотря на некоторое снижение быстродействия сервера Web, данный режим будет полезен при отладке новых приложений. Если установить флажок у этого переключателя, сбои в работе данного приложения не скажутся на общей работоспособности сервера Web.

Панель, показанная на рис. 9-1, позволяет настроить и другие важные параметры приложения. Например, можно запретить кэширование, отключить механизм сеансов, разрешить отладку серверных и клиентских сценариев и т. д. Полную информацию о настройке параметров виртуальных каталогов Вы найдете в электронной справочной системе или в документации к Microsoft Internet Information Server.

Вернемся к нашему приложению.

Подготовив каталог на сервере Web, скопируйте в него файл HelloASP.asp, содержимое которого Вы найдете в листинге 9-1.

Листинг 9-1. Вы найдете в файле chap09\HelloASP.asp на прилагаемом к книге компакт-диске

Рассмотрим подробно содержимое этого файла.

Первая строка содержит оператор @LANGUAGE, который указывает, что это серверный сценарий на языке JScript:

<%@ LANGUAGE = "JScript" %>

Этот оператор, как и все конструкции серверного сценария в документах ASP, должен быть выделен при помощи последовательностей символов “<%” (открывающая последовательность) и “%>” (закрывающая последовательность).

Далее в файле определяется переменная sHelloMsg. Ей присваивается значение текстовой строки “Hello, ASP World!”:

<%
var sHelloMsg = "Hello, ASP World!";
%>

Конструкция <%=sHelloMsg%> вставляет в код динамически создаваемого документа HTML содержимое переменной sHelloMsg:

<HTML>
<BODY>
<H1><%=sHelloMsg%></H1>
</BODY>
</HTML>

В результате в окно браузера (рис. 9-2) будет загружен документ HTML, исходный текст которого приведен ниже:

<HTML>
<BODY>
<H1>Hello, ASP World!</H1>
</BODY>
</HTML>

Вы можете увидеть этот текст, выбрав строку Source из меню View в главном окне браузера. Обратите внимание, что в документе нет последовательностей символов «<%» и «%>». Все конструкции, содержащие такие последовательности, интерпретируются сервером. Они никогда не попадают в создаваемый документ HTML.

Рис. 9-2. Просмотр страницы HelloASP.asp в окне браузера

Пример с циклом

Теперь мы рассмотрим более сложный пример страницы ASP, содержащий серверный сценарий генерации таблицы квадратов целых чисел от 0 до 5. При работе с базой данных Вам часто придется отображать отчеты в табличном виде на основе данных, полученных в результате выполнения запроса. При этом для формирования таблицы Вы сможете воспользоваться приемами, описанными в этом разделе.

Исходный текст страницы ASP, создающей таблицу, приведен в листинге 9-2.

Листинг 9-2. Вы найдете в файле chap09\ForASP.asp на прилагаемом к книге компакт-диске

Первая строка файла страницы ForASP.asp содержит оператор @LANGUAGE, определяющий язык серверного сценария:

<%@ LANGUAGE = "JScript" %>

Заголовок таблицы оформлен как обычно при помощи стандартных тегов языка HTML. Что же касается строк со значениями, то они формируются серверным сценарием в цикле:

<TABLE BORDER="1">
<TR><TH>
Значение X</TH><TH>Значение X*X</TH></TR>
<%
var i;
for(i=0; i<=5; i++)
{
%>
<TR><TD><%=i%></TD><TD><%=i * i%></TD></TR>
<%
}
%>
</TABLE>

Счетчиком цикла служит переменная i, принимающая значения от 0 до 5. При помощи конструкции <%=i%> мы вставляем в ячейки каждой строки текущее значение переменной i, а с помощью конструкции <%=i * i%>  значение квадрата этой переменной.

Ниже мы приводим исходный текст документа HTML, создаваемого при помощи страницы ForASP.asp. Как видите, получившийся документ HTML не содержит никаких строк сценариев:

<HTML>
<BODY>
<H2>Таблица квадратов целых чисел от 0 до 5</H2>
<TABLE BORDER="1">
<TR><TH>Значение X</TH><TH>Значение X*X</TH></TR>
<TR><TD>0</TD><TD>0</TD></TR>
<TR><TD>1</TD><TD>1</TD></TR>
<TR><TD>2</TD><TD>4</TD></TR>
<TR><TD>3</TD><TD>9</TD></TR>
<TR><TD>4</TD><TD>16</TD></TR>
<TR><TD>5</TD><TD>25</TD></TR>
</TABLE>
</BODY>
</HTML>

Внешний вид получившейся таблицы после загрузки документа в окно браузера показан на рис. 9-3.

Рис. 9-3. Просмотр страницы ForASP.asp в окне браузера

Обработка формы

Наше следующее приложение Web  запрашивает у пользователя регистрационную информацию, а затем показывает ее пользователю в окне браузера. Цель данного примера — показать, как с помощью серверных сценариев в страницах ASP можно получить доступ к данным, введенным при помощи форм.

На рис. 9-4 изображена форма запроса идентификатора и пароля пользователя. Она предназначена для подключения к нашему приложению Web. Предполагается, что пользователь введет данные регистрации и щелкнет кнопку Подключиться. Кнопка Отменить предназначена для удаления содержимого из полей формы.

Рис. 9-4. Форма для запроса идентификатора и пароля пользователя

В нашем простом примере никакого подключения не происходит. Вместо этого сервер Web создает и отправляет пользователю страницу HTML с регистрационной информацией (рис. 9-5).

Рис. 9-5. Просмотр регистрационной информации

Форма находится в обычном документе HTML (листинг 9-3) и не имеет никаких особенностей. В частности, здесь мы не применяем клиентских сценариев для проверки правильности введенных данных.

Листинг 9-3. Вы найдете в файле chap09\LoginForm.html на прилагаемом к книге компакт-диске

В качестве значения параметра ACTION тега <FORM> мы указали адрес URL страницы ASP (страница находится в том же каталоге, что и файл LoginForm.html, поэтому адрес URL задан просто именем файла):

<form action="LoginCheck.asp" method=”POST”>

Для передачи данных формы мы использовали метод POST. Можно применить и метод GET, однако, как Вы знаете, ему свойственны ограничения по длине передаваемых данных.

Теперь наша задача — составить серверный сценарий, принимающий данные из полей формы и отправляющий их назад пользователю в виде динамически созданного документа HTML. Исходный текст такого сценария приведен в листинге 9-4.

Листинг 9-4. Вы найдете в файле chap09\LoginCheck.asp на прилагаемом к книге компакт-диске

Для извлечения значений параметров, переданных странице ASP (в нашем случае это значения полей формы) мы применили объект Request. Этот объект предназначен специально для получения информации от пользователя:

<%@ LANGUAGE = "JScript" %>
<HTML>
<HEAD>
<%
var sLogin=Request.Form("Login");
var sPassword=Request.Form("Password");
%>
</HEAD>

Метод Form объекта Request позволяет извлечь содержимое полей формы, переданные методом POST. Наш сценарий сохраняет извлеченные таким образом значения идентификатора пользователя и его пароль и затем записывает их в переменные с именами sLogin и sPassword соответственно. Содержимое этих переменных отображается в ячейках таблицы:

<TABLE>
<TR><TD>Идентификатор:</TD><TD><b><%=sLogin%></b></TD></TR>
<TR><TD>Пароль:</TD><TD><b><%=sPassword%></b></TD></TR>
</TABLE>

Комбинирование клиентского и серверного сценариев

Если Вы разрабатываете административную часть приложения Web (например, программу, предназначенную для просмотра и редактирования списка клиентов электронного магазина) наряду с серверными сценариями можно широко использовать клиентские. В нашем следующем примере мы так и поступаем.

В листинге 9-5 представлены исходные тексты модифицированной формы регистрации, изображенной ранее на рис. 9-4.

Листинг 9-5. Вы найдете в файле chap09\LoginFormEx.html на прилагаемом к книге компакт-диске

Теперь мы добавили к этой форме функцию checkForm, составленную на языке сценариев JavaScript. Эта функция получает управление при завершении ввода данных в поля формы, чтобы проверить, что пользователь указал идентификатор и пароль:

<script LANGUAGE="JavaScript">
<!--
function checkForm()
{
  if(document.RegForm.Login.value == "" ||
     document.RegForm.Password.value == "")
  {
     alert("Укажите идентификатор и пароль");   return;
  }
  document.RegForm.submit();
}
// -->
</script>

Обращаем Ваше внимание на изменения, которые претерпел исходный текст формы по сравнению с листингом 3-3.

Во-первых, кнопка Подключиться имеет тип button, а не submit. Теперь она применяется не для непосредственного отправления данных формы на сервер, а только для вызова функции checkForm, определенной как обработчик события onClick:

<form action="LoginCheckEx.asp" method="POST" name="RegForm">
  <table border="0" width="40%">
     <tr>
       <td width="29%">
Идентификатор:</td> <td width="71%">
       <input type="text" name="Login" size="20"></td> </tr>
     <tr>
       <td width="29%">
Пароль:</td><td width="71%">
       <input type="password" name="Password" size="20"></td> </tr>
     <tr><td width="29%">
       <input type="button" onClick="checkForm();"
          value="
Подключиться" name="Ok"></td><td width="71%">
       <input type="reset" value="
Отменить" name="Cancel"></td>
     </tr>
  </table>
</form>

Во-вторых, к тегу <FORM> мы добавили параметр NAME, определяющий имя формы как RegForm. Это имя потребуется нам для ссылки на поля формы в клиентском сценарии.

И наконец, в-третьих, теперь в параметре ACTION указано имя другой страницы ASP.

Функция checkForm выполняет простейшую проверку — указал ли пользователь идентификатор и пароль. Если что-то пропущено, на экране пользователя появляется сообщение об ошибке. Если же пользователь все данные ввел правильно, функция checkForm отправляет их на сервер при помощи метода document.RegForm.submit.

Эта незамысловатая операция уменьшает количество обращений на сервер Web, отсекая пользователей, не указавших свои пароли или имена.

Страница ASP, получает управление, когда пользователь щелкнет кнопку Подключиться. Она содержит как серверный, так и клиентский сценарий (листинг 9-6).

Листинг 9-6. Вы найдете в файле chap09\LoginCheckEx.asp на прилагаемом к книге компакт-диске

Задача серверного сценария, строки которого выделены символами «<%» и «%>», — извлечение идентификатора пользователя и пароля из данных формы с целью отображения в окне браузера (как и в предыдущем примере):

<%
var sLogin=Request.Form("Login");
var sPassword=Request.Form("Password");
%>

Кроме того, серверный сценарий используется для  формирования таблицы:

<TABLE>
  <TR><TD>Идентификатор:</TD><TD><b><%=sLogin%></b></TD></TR>
  <TR><TD>Пароль:</TD><TD><b><%=sPassword%></b></TD></TR>
  <TR><TD COLSPAN="2"><input type="button" onClick="goBack();"
       value="Назад" name="back"></TD></TR>
</TABLE>

Что же касается клиентского сценария, то он состоит из одной функции goBack:

<script LANGUAGE="JavaScript">
<!--
function goBack()
{
  window.location.href =
     "LoginFormEx.html?"+"FRCE="+Math.random().toString();
}
// -->
</script>

Эта функция получает управление после щелчка пользователем кнопки Назад, добавленной в таблицу (рис. 9-6). Она загружает в окно браузера документ с формой регистрации, расположенной в файле LoginFormEx.html.

Для отключения механизма кэширования мы применяем здесь технику, описанную ранее и основанную на добавлении к имени документа HTML фиктивного параметра в виде произвольной текстовой строки. В этом случае каждый раз при загрузке этого документа браузер будет считать его новым и не станет восстанавливать из кэша предыдущую копию.

Рис. 9-6. Кнопка Назад предназначена для возврата к форме регистрации

Приложения ASP и сеансы

До сих пор при создании простейших приложений Web средствами ASP мы допускали некоторые упрощения. Теперь настало время определить такое понятие, как приложение ASP.

Фактически это подмножество приложений Web, созданных с использованием технологии активных серверных страниц ASP и сервера Microsoft Internet Information Server.

Приложение ASP должно располагаться в отдельном виртуальном каталоге сервера Web или занимать корневой каталог виртуального сервера Web. В этом каталоге необходимо разместить:

·         документ HTML или страницу ASP, которая загружается по умолчанию, когда посетитель указывает адрес URL данного каталога в своем браузере;

·         специальный текстовый файл с именем global.asa, определяющий обработчики событий, возникающих в процессе работы приложения ASP;

·         каталоги, содержащие обычные документы HTML, активные страницы ASP, графические изображения, элементы управления ActiveX, аплеты Java и другие объекты, имеющие отношение к приложению.

Что касается документа HTML или страницы ASP, загружаемой по умолчанию при доступе к каталогу приложения ASP, то его имя определяется при настройке параметров сервера Web. По умолчанию сервер Microsoft Internet Information Server использует для этой цели имя default.htm, однако Вы можете изменить его на более привычное index.html или любое другое.

Файл global.asa, строго говоря, создавать не обязательно. Однако он необходим, если Вы собираетесь отслеживать события, имеющие отношение ко всему приложению, или сохранять информацию в глобальных переменных приложения.

Когда пользователь загружает страницу приложения ASP в свой браузер, начинается сеанс его работы с приложением. В рамках сеанса создаются локальные (для данного сеанса) переменные, недоступные другим пользователям, работающим с этим же приложением. О применении таких переменных Вы узнаете чуть позже.

Файл global.asa

Как мы только что сказали, файл global.asa имеет отношение к приложению ASP в целом и создается для каждого такого приложения. Он должен находится в корне виртуального каталога приложения ASP или в корне виртуального сервера Web.

В этом файле определены обработчики следующих событий:

·         запуск приложения ASP;

·         останов приложения ASP;

·         начало сеанса пользователя, загрузившего в свой браузер главную страницу приложения ASP;

·         завершение сеанса пользователя с приложением ASP.

Для каждого такого события Вы можете назначить индивидуальные обработчики в виде серверных сценариев. Эти сценарии выполняют такие функции, как инициализация глобальных переменных приложения и так называемых переменных сеанса, создаваемых в рамках сеанса пользователей, выполнение операций с cookie, подключение к базам данных и т. д. Словом, сценарии файла global.asa предназначены для выполнения действий, которые затрагивают приложение в целом.

Система разработки приложений Microsoft InterDev создает пустой шаблон файла global.asa автоматически. Он имеет следующий вид:

<SCRIPT LANGUAGE=VBScript RUNAT=Server>

' Обработчик события Session_OnStart
Sub Session_OnStart
' Тело обработчика события Session_OnStart
End Sub

' Обработчики других событий
' . . .
</SCRIPT>

Обращаем Ваше внимание, что в теге <SCRIPT> указан параметр RUNAT=Server. Он свидетельствует, что описанный этим тегом сценарий должен выполняться не браузером, а сервером, то есть это серверный сценарий.

Список возможных событий, обрабатываемых в файле global.asa, перечислен в таблице 9-1.

Таблица 9-1. События, обрабатываемые в файле global.asa

Событие

Когда возникает

Session_OnStart

Пользователь впервые загружает любую страницу приложения

Session_OnEnd

Пользователь завершает работу с приложением, или истекает период ожидания

Application_OnStart

Любой пользователь загружает впервые любую страницу приложения

Application_OnEnd

Сервер Web завершает свою работу

 

Отслеживая события в файле global.asa, приложение ASP определяет, когда к нему подключился очередной пользователь и когда он отключился. При этом автоматически учитываются такие нюансы, как просмотр пользователем в окне его браузера других серверов Web и последующий возврат пользователя на страницу Вашего сервера. Кроме того, учитывается, что при передаче данных по ненадежным каналам Интернета могут возникать значительные задержки. Если задержка превышает 20 минут (время можно задать самостоятельно), сервер Web считает, что сеанс завершен. При этом возникает событие Session_OnEnd.

В общем случае логика обработки событий в файле global.asa во многом определяется логикой работы Вашего приложения. Вполне вероятно, Вам не потребуется отслеживать моменты начала и завершения сеансов пользователей, хотя лучше это все-таки делать. Например, если сеанс завершился по истечении периода ожидания, приложение может отключить пользователя и запросить пароль при попытке повторного подключения.

Событие Application_OnStart удобно применять для инициализации и загрузке элементов управления ActiveX, которые в результате выполнения такой операции станут доступными всем пользователям.

Заметим, что файл global.asa может быть составлен и с применением языка сценариев JavaScript. В этом случае в нем должны быть определены функции с именами Session_OnStart, Session_OnEnd, Application_OnStart и Application_OnEnd. В документации и примерах, подготовленных Microsoft, почти повсеместно демонстрируется использование в этом файле сценариев VB Script. Мы же, напротив, будем работать со сценариями JavaScript и JScript.

Переменные приложений ASP

Приложения Web, составленные с применением ASP, могут создавать глобальные переменные, доступные всем пользователям данного приложения, а также переменные сеанса, доступные только отдельным клиентам во время их текущего сеанса с сервером.

Глобальные переменные приложения создаются и инициализируются обработчиками событий в файле global.asa. Их применяют для хранения значений, необходимых всем пользователям приложения. Так, для электронного магазина это может быть, например, текущий курс обмена валют, или значения скидок, действующих для пользователей определенной категории, или ссылки на какие-либо глобальные объекты.

Переменные сеанса более предназначены для хранения информации, связанной с пользователями — идентификатора текущего пользователя и его пароля, кода места проживания, нужного для вычисления стоимости доставки товара, прав пользователя или другой аналогичной информации.

Переменные сеанса также годятся для передачи данных между различными страницами ASP. Например, на одной странице Вы задаете параметры запросов, а на другой конструируете форму запроса в зависимости от этих параметров. Так как пользователи имеют свои собственные переменные сеанса, они вправе хранить в них собственные данные, доступные из всех страниц ASP приложения.

Заметим, что переменные сеанса и объект Session, предназначенный для работы с ними, доступны только в том случае, если пользователь разрешил в параметрах браузера действие Cookie (приложение ASP также может запретить применение Cookie).

Это связано с тем, что механизм сеансов основан на хранении в Cookie глобальных уникальных идентификаторов сеанса. Поэтому когда клиент отключает их, все переменные сеанса сохраняют свои значения только в пределах одной страницы ASP. В этом случае Вы не сможете их применить, например, для передачи информации из одной страницы в другую.

В качестве альтернативы передачи параметров между страницами ASP допустимо использовать другие способы, не зависящие от Cookie и сеансов. Например, передачу параметров в строке ссылки на страницу ASP или в скрытых полях форм.

Практическое применение ASP

На примере нескольких несложных приложений ASP мы покажем технику использования важнейших средств ASP, таких, как переменные сеанса и приложения. Мы также приведем исходные тексты примера приложения ASP, использующего файл global.asa для хранения количества текущих сеансов и текстовой строки в глобальной переменной приложения.

Создание мастера средствами ASP

Вначале мы покажем Вам, как пользоваться переменными сеанса, попутно решая практическую задачу — создание мастера платежей средствами ASP.

Наш мастер платежей, как и мастера в обычных приложениях Windows, состоит из набора страниц, связанных между собой кнопками просмотра. Пользователь может перемещаться по ним в обоих направлениях, устанавливая на страницах различные параметры. Нам мастер поможет решить простейшую задачу — выбрать валюту и тип кредитной карточки для оплаты товара. Применяя использованные нами решения, Вы сможете создать мастера для выполнения любых других операций, например: для выбора способа доставки товара, для создания системы поиска товара в каталогах и т. д.

Первая страница мастера платежей показана на рис. 9-7.

Рис. 9-7. Первое окно мастера платежей

Она играет роль главной страницы мастера платежей и представляет собой обычный документ HTML с формой, содержащей одну-единственную кнопку Вперед. Если Вы щелкнете эту кнопку, на экране появится следующее окно мастера, показанное на рис. 9-8.

В нем заданы три переключателя, позволяющие выбрать для оплаты товара рубли, доллары или немецкие марки (Вы, конечно, можете добавить евро и любые другие валюты).

Если Вы щелкнете кнопку Назад или Отменить, на экране появится главная страница мастера (рис. 9-7), если же кнопку Вперед — перейдете к третьей странице нашего мастера платежей.

Третья страница показана на рис. 39. Список и кнопки на ней аналогичны элементам на второй странице.

Рис. 9-8. Выбор валюты

Если, находясь на третьей странице мастера, Вы щелкнете кнопку Назад, то снова окажетесь на предыдущей странице, предназначенной для выбора валюты.

Рис. 9-9. Выбор типа кредитной карточки

Заметим, что после возврата к предыдущей странице указанный Вами ранее тип валюты будет сохранен. Этот эффект достигается с помощью записи кода выбранной валюты в переменную сеанса.

В следующей странице мастера наше приложение Web показывает, какая валюта и какая кредитная карточка использованы при покупки (рис. 9-10). Здесь Вы также можете разместить кнопку для перехода на страницу, завершающую процесс покупки снятием денег со счета посетителя Вашего магазина. Нажимая кнопку, пользователь отправляется на страницу сервера Web процессингового центра, где и происходит автоматическое снятие денег (с одобрения пользователя и при его участии). Там он, в частности, вводит номер кредитной карточки.

Кнопка Назад, как и раньше, позволяет вернуться к предыдущей странице мастера. Если Вы щелкнете ее, то увидите, что в появившемся списке типов кредитных карточек выделен ранее выбранный Вами тип. Как Вы уже, наверное, догадались, указанный посетителем магазина тип кредитной карточки мы храним в переменной сеанса.

Кнопка Отменить отсылает посетителя на главную страницу мастера платежей.

Рис. 9-10. Завершающее окно мастера платежей

Теперь, когда мы рассказали Вам о назначении и работе страниц мастера, перейдем к описанию исходных текстов этих страниц.

Для обеспечения максимальной совместимости мастера платежей с обозревателями различных типов мы решили совсем не использовать в нем клиентские сценарии, ограничившись только средствами серверных сценариев ASP. В результате отсылаемые посетителям страницы представляют собой простые документы HTML, не “отягощенные” удобными и мощными, но сомнительными с точки зрения совместимости конструкциями на языке сценариев JavaScript.

Исходный текст главной страницы мастера показан в листинге 9-7.

Листинг 9-7. Вы найдете в файле chap09\Master0.html на прилагаемом к книге компакт-диске

Она содержит обычную форму с кнопкой типа submit:

<form action="Master1.asp">
  <table border="0" width="300" cellpadding="2">
     <tr><td width="100">
     <input type="submit" value="
Вперед &gt;&gt;" name="B2">
     </td></tr>
  </table>
</form>

Если щелкнуть ее мышью, в окно браузера загрузится документ из файла Master1.asp, указанный в параметре ACTION тега <FORM>.

Текст файла Master1.asp представлен в листинге 9-8. Помимо таблиц и форм, он содержит серверный сценарии, составленный на языке JScript.

Листинг 9-8. Вы найдете в файле chap09\Master1.asp на прилагаемом к книге компакт-диске

Первая строка файла Master1.asp сообщает серверу Web о том, что данный файл содержит серверный сценарий, составленный на языке JScript. С этой конструкцией Вы уже встречались. А вот вторая строка для Вас новая:

<%Response.Expires=0%>

Записывая нулевое значение в свойство Expires объекта Response, мы тем самым сообщаем обозревателю, что полученная им страница уже устарела. В результате он не будет ее кэшировать. Это еще один способ отменить кэширование страниц, мешающее обновлению динамически создаваемых документов HTML в окне браузера. К сожалению, данное решение работает не всегда. Более надежный способ предполагает добавление к адресу URL страницы при ее загрузке фиктивного параметра в виде случайного числа.

Следующее действие серверного сценария — считывание содержимого переменной сеанса с именем sessCurrency. Эта операция выполняется при помощи объекта Session:

var sCurrency = Session("sessCurrency");

Когда посетитель попадает на эту страницу в первый раз, такой переменной сеанса еще не существует. Поэтому в локальную переменную sCurrency занесено значение null. Когда же пользователь вернется на вторую страницу мастера с последующих страниц, переменная сеанса sessCurrency уже содержит код выбранной валюты.

Чтобы при повторных отображениях был помечен переключатель, соответствующий выбранной ранее валюте, необходимо при генерации кода HTML указать в соответствующем теге <INPUT> параметр checked. Для этого мы предусмотрели в сценарии ASP три локальные переменные с именами sChkRub, sChkDollar и sChkDM. С помощью конструкции if-else в одну из этих переменных записывается текстовая строка “checked”. В дальнейшем мы используем выражения вида <%=sChkRub%>, чтобы определить параметры тегов <INPUT>. Это позволяет нам отметить только один из трех переключателей, осуществляющих выбор валюты:

<%
var sCurrency = Session("sessCurrency");
var sChkRub="";
var sChkDollar="";
var sChkDM="";

if(sCurrency == "rub")
  sChkRub="checked";
else if(sCurrency == "dollar")
  sChkDollar="checked";
else if(sCurrency == "dm")
  sChkDM="checked";
else
  sChkRub="checked";
%>
<form id="form1" name="form1" action="Master2.asp" method="POST">
  <table border="0" cellPadding="0" cellSpacing="0" width="157">
     <tr><td width="27">
       <input id="radio1" name="Currency" type="radio" value="rub" <%=sChkRub%>><br>
       <input id="radio2" name="Currency" type="radio" value="dollar" <%=sChkDollar%>><br>
       <input id="radio3" name="Currency" type="radio" value="dm" <%=sChkDM%>></td><td width="118">
рубли<br>доллары<br>немецкие марки</td></tr>
  </table>
  <table border="0" width="300" cellpadding="2"><tr><td width="100">
     <input type="submit" value="
Вперед >>" name="B2"></td></tr>
  </table>
</form>

Такой подход позволил нам определять начальное положение переключателя с зависимой фиксацией из серверного сценария, расположенного в странице ASP. Причем, что важно, мы делаем это без использования клиентских сценариев, применение которых черевато возникновением потенциальных проблем совместимости с браузерами различных типов.

Теперь мы расскажем о том, как реализованы переходы между страницами нашего мастера платежей.

Кнопку Вперед надо поместить в ту же форму, что и переключатели выбора валюты. Такая необходимость вызвана тем, что, щелкнув ее, Вы передадите управление следующей странице мастера. Эта страница должна извлечь состояние переключателя выбора валюты, передаваемое вместе с содержимым формы.

Кнопки Назад и Отмена также следует расположить в отдельных формах, так как они предназначены для загрузки разных страниц. Предусмотрев для этих кнопок разные формы, мы можем указать в соответствующих параметрах action тега <FORM> различные адреса URL. В первой странице мастера в результате щелчка кнопок Назад и Отмена загружается одна и та же страница Master0.html, однако во второй странице Master2.asp это уже будет не так.

Рассмотрим исходный текст второй страницы мастера платежей, приведенный в листинге 9-9.

Листинг 9-9. Вы найдете в файле chap09\Master2.asp на прилагаемом к книге компакт-диске

В этом листинге после обычных строк, определяющих язык серверного сценария и отменяющих кэширование, находятся строки, извлекающие код выбранной валюты. Он извлекается из параметров, переданных вместе с данными формы предыдущей страницей мастера, и записывается в переменную sCurrency:

<%
Response.Expires=0;
var sCurrency;
if(Request.Form("Currency").Count != 0)
{
  sCurrency=Request.Form("Currency")(1);
  Session("sessCurrency")=sCurrency;
}
else
  sCurrency=Session("sessCurrency");
var sCurrencyName="";
%>

Однако файл Master2.asp может быть загружен не только в результате щелчка кнопки Вперед, расположенной на предыдущей страницы мастера, но и в результате щелчка кнопки Назад, расположенной на следующей странице Master3.asp. В последнем случае загрузка файла Master2.asp будет выполняться из другой формы, не содержащей переключателя с именем Currency.

Поэтому мы вначале определяем, если ли элементы в наборе Form("Currency"), применяя следующую конструкцию:

if(Request.Form("Currency").Count != 0)
{
  . . .
}

Когда пользователь «листает» страницы мастера в прямом направлении, этот набор содержит один такой элемент с номером 1. Мы извлекаем его при помощи объекта Request и сохраняем в сеансовой переменной sessCurrency:

sCurrency=Request.Form("Currency")(1);
Session("sessCurrency")=sCurrency;

Когда же пользователь «листает» страницы мастера в обратном направлении, сеансовая переменная sessCurrency уже создана и проинициализирована. Наш сценарий извлекает из нее код выбранной валюты обычным образом и записывает в переменную sCurrency:

sCurrency=Session("sessCurrency");

На следующем этапе в зависимости от содержимого переменной sCurrency сценарий записывает ту или иную текстовую строку с названием валюты в переменную sCurrencyName, которую мы используем для подготовки текста сообщения с названием валюты (в виде конструкции <%=sCurrencyName%>).

<%
if(sCurrency == "rub")
  sCurrencyName = "
рубли";
else if(sCurrency == "dollar")
  sCurrencyName = "
доллары";
else if(sCurrency == "dm")
  sCurrencyName = "
немецкие марки";
%>

Третья страница мастера Master2.asp содержит список типов кредитных карточек. Покупатель должен выбрать из него ту, которую он будет использовать для оплаты. Инициализация данного списка должна выполняться с учетом того, что пользователь может проходить страницы мастера как в прямом, так и в обратном направлении.

Когда покупатель «листает» страницы в прямом направлении и впервые попадает на страницу Master2.asp, переменная сеанса sessWirecard с кодом кредитной карточки еще не определена. В этом случае наш сценарий выбирает по умолчанию кредитную карточку VISA, записывая в переменную swChkVisa строку “selected”. Эта строка вместе со строками swChkMaster и swChkAEx применяется (при помощи конструкции типа <%=swChkVisa%>) при формировании списка типов кредитных карточек:

<%
var sW=Session("sessWirecard")
var swChkVisa="";
var swChkMaster="";
var swChkAEx="";

if(sW == "VISA")
  swChkVisa="selected";
else if(sW == "Mastercard")
  swChkMaster="selected";
else if(sW == "American_Express")
  swChkAEx="selected";
else
  swChkVisa="selected";
%>

Только в одной из переменных swChkVisa, swChkMaster и swChkAEx может содержаться строка “selected”, остальные будут пустыми. В результате единственный тип кредитной карточки выбирается по умолчанию в списке <SELECT> с именем PayMethod.

Заметим, что указанный список находится в одной форме с кнопкой Вперед.

<form id="form1" name="form1" action="Master3.asp" method="post"><p>
  <select name="PayMethod" size="1">
     <option <%=swChkVisa%> value="VISA">VISA</option>
     <option <%=swChkMaster%> value="Mastercard">Mastercard</option>
     <option <%=swChkAEx%> value="American_Express">American Express</option>
  </select></p>
  <table border="0" width="300" cellpadding="2">
     <tr><td width="100">
     <input type="submit" value="
Вперед >>" name="B2"></td></tr>
  </table>
</form>

Если щелкнуть эту кнопку, в окно обозревателя начнет загружаться следующая страница мастера платежей из файла Master3.asp.

Что же касается кнопок Назад и Отменить, то соответствующие им формы ссылаются на страницы Master1.asp и Master0.html соответственно:

<form id="form0" name="form0" action="Master1.asp">
  <table border="0" width="100" cellpadding="2">
     <tr><td width="1" align="left">
     <input type="submit" value=" <<
Назад" name="B1"></td></tr>
  </table>
</form>   </td><td>
<form id="form2" name="form2" action="Master0.html">
  <table border="0" width="102" cellpadding="2">
     <tr><td width="1" align="left">
     <input type="submit" value="
Отменить" name="B3"></td></tr>
  </table>
</form>  

Последняя страница нашего мастера платежей (листинг 9-10) предназначена для отображения выбранной валюты и типа кредитной карточки, использованной для покупки.

Листинг 9-10. Вы найдете в файле chap09\Master3.asp на прилагаемом к книге компакт-диске

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

<%
Response.Expires=0;
var sWirecard;
if(Request.Form("PayMethod").Count != 0)
{
  sWirecard=Request.Form("PayMethod")(1);
  Session("sessWirecard")=sWirecard;
}
else
  sWirecard=Session("sessWirecard");
%>

Напомним, что эта переменная сеанса используется предыдущей страницей мастера для инициализации списка типов кредитных карточек.

Если мы попадаем на последнюю страницу мастера с предыдущей страницы, наш сценарий запрашивает выбранный тип кредитной карточки и сохраняет его в переменной сеанса sessWirecard:

sWirecard=Request.Form("PayMethod")(1);
Session("sessWirecard")=sWirecard;

В противном случае этот код считывается в переменную sWirecard при помощи объекта Session из существующей переменной сеанса:

sWirecard=Session("sessWirecard");

При формировании текстового сообщения о платеже сценарий использует локальные переменные sCurrencyName и sWirecardName. Они заполняются с применением операторов case:

<%
var sCurrencyName="";
switch(Session("sessCurrency"))
{
case "rub": sCurrencyName="
Рубли"; break;
case "dollar":   sCurrencyName="
Доллары"; break;
case "dm":  sCurrencyName="
Немецкие марки"; break;
default: sCurrencyName="
ОШИБКА. Сообщите администратору сервера"; break;
}
var sWirecardName="";
switch(Session("sessWirecard"))
{
case "VISA":  sWirecardName="VISA"; break;
case "Mastercard": sWirecardName="Mastercard"; break;
case "American_Express":  sWirecardName="American Express"; break;
default: sWirecardName="
ОШИБКА. Сообщите администратору сервера"; break;
}
%>

Обратим Ваше внимание на строку «default» этого оператора. Если в работе нашего приложения Web возникла ошибка (например, неверны ссылки на страницу), вместо названия валюты и кредитной карточки мы выводим соответствующее сообщение. Вы можете, например, добавить в него ссылку на почтовый адрес администратора сети или что-нибудь еще.

На последней странице нашего демонстрационного мастера нет кнопки Вперед или какой-либо ссылки на другие страницы, однако в реальных приложениях стоит дополнить мастер страницами, запрашивающими такую информацию, как номер кредитной карточки и срок ее действия.

Подсчет количества активных сеансов

В этом примере, представляющем собой простейший шаблон приложения ASP, мы демонстрируем использование переменных приложения для подсчета количества активных сеансов. 

В качестве главной страницы приложения выступает файл default.asp (листинг 9-12), расположенный в корне виртуального каталога SessCounter. Если загрузить данный файл в окно браузера, Вы увидите заголовок Session counter и количество активных сеансов. На рис. 9-11 показан внешний вид окна после активизации четырех сеансов одновременно.

Рис. 9-11. Четыре сеанса находятся в активном состоянии

Чтобы активизировать несколько сеансов, Вы можете открыть эту страницу в нескольких окнах браузера на одном компьютере или на нескольких компьютерах в своей локальной сети.

Помимо файла default.asp, в корне виртуального каталога SessCounter находится файл global.asa, исходный текст которого показан в листинге 9-11.

Листинг 9-11. Вы найдете в файле chap09\Counter/global.asa на прилагаемом к книге компакт-диске

Первая строка определяет язык сценария, а также указывает, что сценарий должен исполняться на сервере:

<SCRIPT LANGUAGE=JSCRIPT RUNAT=Server>

Обратите внимание, что он написан на языке сценариев JScript, а не VB Script, что характерно для всех примеров приложений Microsoft и других книг, посвященных ASP.

Функция Application_OnStart получает управление, когда любой пользователь в первый раз загружает главную страницу нашего приложения:

function Application_OnStart()
{
  Application("sess_counter") = 0;
  Application("appl_name") = "Session counter";
}

В ее задачу входит создание и инициализация переменных приложения sess_counter и appl_name. Первая из этих переменных содержит счетчик активных сеансов, а вторая — текстовую строку «Session counter», которая будет отображаться в окне браузера.

Когда очередной пользователь загружает главную страницу нашего приложения в окно браузера, управление передается функции Session_OnStart:

function Session_OnStart()
{
  Application("sess_counter") = Application("sess_counter") + 1;
}

Эта функция увеличивает значение переменной приложения sess_counter на единицу.

При отключении пользователя от приложения функция Session_OnEnd уменьшает значение счетчика sess_counter на единицу:

function Session_OnEnd()
{
  Application("sess_counter") = Application("sess_counter") - 1;
}

Что же касается функции Application_OnEnd, то она определена как заглушка и не выполняет никаких действий:

function Application_OnEnd()
{
}

Файл default.asp (листинг 9-12) отображает в окне браузера количество активных сеансов.

Листинг 9-12. Вы найдете в файле chap09\Counter/default.asp на прилагаемом к книге компакт-диске

В качестве заголовка создаваемого документа используется содержимое глобальной переменной appl_name:

<%
var sHelloMsg = Application("appl_name");
%>
<HTML>
<BODY>
<H1><%=sHelloMsg%></H1>

Количество активных сеансов извлекается из переменной приложения sess_counter:

<p>Количество активных сеансов: <%=Application("sess_counter")%>

Использование Cookie в сценариях ASP

В предыдущей главе мы рассказывали о Cookie и привели примеры клиентских сценариев, работающих с Cookie. Серверные сценарии также способны выполнять операции с Cookie, причем использование их вместо клиентских сценариев благоприятно скажется на совместимости Вашего приложения с браузерами различных типов.

Для установки значения Cookie Вам придется воспользоваться свойством Cookies объекта Response:

Response.Cookies("bgColor")=”White”;

Эту строку надо расположить на странице ASP перед тегом <HTML>.

Если Вам нужно получить значение Cookie, это легко сделать в серверном сценарии, обратившись к свойству Cookies объекта Request, например:

var sCount;
sCount=Request.Cookies("Count");

Устанавливая свойство Response.Cookies.Expires, можно задавать дату, по истечении которой Cookie будет удален.

Ниже мы привели фрагмент кода, удаляющий Cookie с именем bgColor:

var d, s;
d = new Date();
d.setTime(d.getTime()-1);
s = d.toLocaleString();
Response.Cookies("bgColor").Expires = s;

Здесь мы вначале получаем текущую дату, создавая объект класса Date. Затем при помощи методов getTime и setTime мы уменьшаем текущую дату на одну микросекунду и преобразуем ее методом toLocaleString в формат, соответствующий текущим локальным параметрам. Только после такого преобразования можно записывать строку даты в свойство Expires объекта Cookies.

В качестве примера обращения к Cookie из серверных сценариев рассмотрим приложение ASP, сохраняющее параметры фона на странице. Во второй главе мы уже создавали аналогичное приложение с применением клиентских сценариев.

На первой странице нашего приложения (рис. 9-12) пользователь может выбрать цвет фона или задать цвет фона по умолчанию.

Рис. 9-12. Выбор цвета фона страницы

Если щелкнуть кнопку Параметры по умолчанию, на экране появится страница со счетчиком количества посещений и счетчиком пользователей, работающих в настоящий момент времени с Вашим приложением (рис. 9-13).

Рис. 9-13. Первое посещение страницы пользователем

При втором и последующих посещениях внешний вид этой страницы изменится (рис. 9-14).

Рис. 9-14. Второе посещение страницы

 Для подсчета активных пользователей, работающих с нашим приложением, мы определили в файле global.asa (листинг 9-13) обработчики событий Application_OnStart, Session_OnStart и Session_OnEnd.

Листинг 9-13. Вы найдете в файле chap09\DemoCookie\global.asa на прилагаемом к книге компакт-диске

 

Первый из них создает и инициализирует переменную приложения с именем sess_counter:

function Application_OnStart()
{
  Application("sess_counter") = 0;
}

Обработчики событий Session_OnStart и Session_OnEnd соответственно увеличивают и уменьшают значение этого счетчика на единицу.

function Session_OnStart()
{
  Application("sess_counter") = Application("sess_counter") + 1;
}
function Session_OnEnd()
{
  Application("sess_counter") = Application("sess_counter") - 1;
}

Исходный текст главной страницы приложения с переключателем выбора цвета фона страницы и двумя кнопками показан в листинге 9-14.

Листинг 9-14. Вы найдете в файле chap09\DemoCookie\default.asp на прилагаемом к книге компакт-диске

Помимо всего прочего, в ней расположена форма, позволяющая выбрать настройки персональной страницы:

<FORM NAME="TestForm" ACTION="main.asp?RESET=0" METHOD="POST">
  <P>
  <INPUT TYPE="submit" VALUE="Переход на страницу">
  <P><HR>
  <P>Настройка параметров персональной страницы
  <P><B>Цвет фона:</B>
  <P><INPUT TYPE="radio" NAME="Color" CHECKED VALUE="White"> Белый
  <BR><INPUT TYPE="radio" NAME="Color" VALUE="Yellow"> Желтый
  <BR><INPUT TYPE="radio" NAME="Color" VALUE="Lime"> Зеленый
  <BR><INPUT TYPE="radio" NAME="Color" VALUE="Fuchsia"> Малиновый
</FORM>

Изучая листинг 9-14, нетрудно заметить, что кнопки Переход на страницу и Параметры по умолчанию расположены в разных формах.

Щелчок кнопки Переход на страницу приводит к вызову страницы main.asp с параметром RESET, равным 0:

<FORM NAME="TestForm" ACTION="main.asp?RESET=0" METHOD="POST">

Обратите внимание, как мы передаем этот параметр из формы в документ ASP, записывая его имя после знака вопроса. Форма с кнопкой Параметры по умолчанию тоже вызывает страницу main.asp, но задает при этом значение параметра RESET, равное 1:

<FORM ACTION="main.asp?RESET=1" METHOD="POST">
  <INPUT TYPE="submit" VALUE="
Параметры по умолчанию" id=reset1 name=reset1>

Если Вы хотите передать таким способом несколько параметров, их нужно отделить друг от друга символами “&”, например:

ACTION="main.asp?RESET=0&MODE=Force&Age=18"

Так, Вы можете добавить параметр в виде символьного представления случайного числа. Это позволит эффективно отключить кэширование загружаемой страницы.

Параметр RESET анализируется серверным сценарием ASP, расположенным на странице main.asp (листинг 9-15).

Листинг 9-15. Вы найдете в файле chap09\DemoCookie\main.asp на прилагаемом к книге компакт-диске

Чтобы получить значение параметра RESET, наш сценарий обращается к объекту Request:

var nCount=0;
if(Request("RESET")(1) == 1)
{
  Response.Cookies("bgColor")="White";
  Response.Cookies("Count")="0";
  nCount=0;
}
else
{
  var sColor=Request.Form("Color")(1);
  Response.Cookies("bgColor")=sColor;

  sCount=Request.Cookies("Count");
  sbgr=Request.Cookies("bgColor");
 
  nCount=sCount;
  nCount++;
  sCount=nCount.toString();
  Response.Cookies("Count")=sCount;
}

В том случае, когда значение этого параметра равно 1, выполняется запись в Cookie значений по умолчанию:

Response.Cookies("bgColor")="White";
Response.Cookies("Count")="0";

Здесь Cookie с именем bgColor хранит цвет фона страницы, а с именем Count — количество посещений этой страницы пользователем.

Если же страница вызывается с параметром RESET, равным 0, наш серверный сценарий определяет, какой цвет выбрал пользователь, запрашивая содержимое поля с именем Color. Полученное значение затем сохраняется в Cookie с именем bgColor:

var sColor=Request.Form("Color")(1);
Response.Cookies("bgColor")=sColor;

Далее серверный сценарий запрашивает содержимое Cookie с именем Count (здесь хранится количество посещений страницы пользователем), увеличивает его на единицу и записывает обратно.

Заголовок страницы при первом и последующих посещениях страницы будет разным. Это достигается размещением на странице следующего фрагмента кода:

<%
if(nCount == 0)
{%>
<H2>Добро пожаловать!</H2>
<%} else {%>
<H2>Добро пожаловать СНОВА!</H2>
<%}%>

Анализируя содержимое переменной nCount, в которой записано текущее значение Cookie с именем Count, серверный сценарий помещает на страницу один из двух заголовков.

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

<%
if(nCount == 0)
{%>
<H2>Добро пожаловать!</H2>
<%} else {%>
<H2>Добро пожаловать СНОВА!</H2>
<%}%>

<p>Вы были здесь <%=Request.Cookies("Count")%> раз<br>
Цвет фона страницы: <%=Request.Cookies("bgColor")%><br>
Всего активных посетителей: <%=Application("sess_counter")%>

Регистрация пользователей

При создании Интернет-магазина или другого коммерческого приложения для Интернета Вам придется решать проблему аутентификации пользователей: как правило, для того чтобы работать со страницами Вашего приложения, пользователи должны будут ввести свой идентификатор и пароль.

В этом разделе мы приведем исходные тексты фрагмента приложения, решающего задачу аутентификации пользователей. По результатам аутентификации им либо разрешается, либо запрещается работать с приложением.

Для ввода идентификатора (имени) и пароля мы используем панель, показанную на рис. 9-15.

Рис. 9-15. Панель для ввода идентификатора и пароля

Предполагается, что данная страница ASP располагается в файле с именем default.asp — он загружается автоматически, когда пользователь просматривает содержимое главного каталога приложения. Напомним, что при настройке сервера IIS Вы можете задать имя документа, загружающегося по умолчанию в окно браузера при этих условиях.

В случае успешной аутентификации в окне браузера появится основная страница приложения, расположенная в файле main.asp (рис. 9-16). В ней отображается идентификатор и пароль подключившегося пользователя.

Рис. 9-16. Пользователь успешно подключился к нашему приложению

Если же идентификатор или пароль введен неправильно, пользователь окажется на странице enter.asp, показанной на рис. 9-17. На этой странице имеется ссылка, с помощью которой можно вернуться к панели ввода идентификатора и пароля.

Рис. 9-17. Результат ввода неправильного идентификатора или пароля

Работа данной системы аутентификации основана на применении переменных сеанса, заданных отдельно для каждого пользователя приложения ASP.

Исходный текст страницы с формой аутентификации показан в листинге 9-16.

Листинг 9-16. Вы найдете в файле chap09\LoginTest\default.asp на прилагаемом к книге компакт-диске

Когда пользователь вводит идентификатор и пароль, эти данные передаются на страницу enter.asp в соответствии с параметрами тега <FORM>:

<FORM ACTION="enter.asp" METHOD="post" TARGET="_top">
  <H1>
Добро пожаловать!</H1>
  <TABLE BORDER=0 CELLPADDING=5 CELLSPACING=0>
     <TR><TD>
Имя</TD><TD>
     <INPUT SIZE=10 TYPE="EDIT" NAME="USR"></TD></TR>
     <TR><TD>
Пароль</TD><TD><nobr>
     <INPUT SIZE=10 TYPE="password" NAME="PWD"><INPUT  TYPE="submit"     
     VALUE="
Вход"></nobr></TD></TR>
  </TABLE>
</FORM>

Исходный текст страницы enter.asp Вы найдете в листинге 9-17.

Листинг 9-17. Вы найдете в файле chap09\LoginTest\enter.asp на прилагаемом к книге компакт-диске

Сценарий на странице enter.asp получает введенные пользователем идентификатор и пароль, сохраняя их в переменных sUser и sPassword соответственно.

var sUser=Request("USR")(1);
var sPassword=Request("PWD")(1);

Далее выполняется процесс аутентификации. В нашем демонстрационном примере мы просто сравниваем имя пользователя со строкой “admin”, а пароль — со строкой “root”:

if(sUser == "admin" && sPassword == "root")
{
  Session("Ok")="Ok";
  Session("UserID")=sUser;
  Session("UserPwd")=sPassword;
  Response.Redirect("main.asp");
}
else
{
  Session("Ok")="";

В следующей главе мы покажем, как выполнять аутентификацию с применением базы данных пользователей.

Если идентификатор и пароль введены правильно, наш сценарий создает переменную сеанса с именем Ok и записывает в нее текстовую строку “Ok”. Дополнительно мы сохраняем идентификатор и пароль пользователя в переменных сеанса с именами UserID и UserPwd.

На следующем этапе мы отправляем успешно подключившегося пользователя на главную страницу приложения main.asp, вызывая для этого метод Redirect объекта Response:

Response.Redirect("main.asp");

В том случае, когда пользователю не удалось подключиться к приложению, серверный сценарий на странице enter.asp формирует документ HTML со ссылкой в виде строки Доступ запрещен. Эта ссылка позволит пользователю перейти на страницу default.asp, где он сможет повторить попытку:

<HTML>
<BODY>
<CENTER><H1><a href=default.asp>
Доступ запрещен</a></H1></CENTER>
</BODY>
</HTML>

Когда Вы изучите наш сценарий подключения, у Вас может возникнуть один вопрос: а что помешает злонамеренному пользователю, знающему адрес URL главной страницы нашего приложения main.asp, попасть туда непосредственно, минуя страницу аутентификации default.asp?

Хороший вопрос. Однако мы предусмотрели такой вариант.

Обратите внимание на исходный текст главной страницы приложения main.asp, представленный в листинге 9-18.

Листинг 9-18. Вы найдете в файле chap09\LoginTest\main.asp на прилагаемом к книге компакт-диске

В отличие от документов HTML, в страницы ASP можно вставлять другие страницы при помощи оператора #include. Главная страница нашего приложения main.asp, как и все остальные страницы (кроме default.asp и enter.asp) включают в себя документы header.asp и footer.asp. Документ header.asp помещается в самое начало любой другой страницы нашего приложения, а документ footer.asp — в конец:

<!-- #include file="header.asp" -->
<h2>Добро пожаловать!</h2>
<p>Вы успешно подключились к нашему приложению.
<p>Ваш идентификатор: <%=Session("UserID")%><br>
Ваш пароль: <%=Session("UserPwd")%></p>
<!-- #include file="footer.asp" -->

Что представляет собой документ header.asp?

Его исходный текст приведен в листинге 9-19.

Листинг 9-19. Вы найдете в файле chap09\LoginTest\header.asp на прилагаемом к книге компакт-диске

При загрузке любой страницы, в начало которой вставлен файл header.asp, выполняется проверка содержимого переменной сеанса с именем Ok:

<%
if(Session("Ok")!="Ok") {
%>
<HTML>
<HEAD>
<META HTTP-EQUIV="Refresh" CONTENT="0; URL=default.asp; target=_top">
</HEAD>
<BODY>
&nbsp;
</BODY>
</HTML>
<% } else { %>
<HTML>
<BODY>

Если аутентификация пользователя прошла успешно, в этой переменной находится строка “Ok”, а если нет — пустая строка (либо такая переменная не определена вовсе).

В случае успешной аутентификации сценарий файла header.asp вставляет в документ теги <HTML> и <BODY>, а при неудаче — тег <META>, принудительно направляющий браузер на страницу аутентификации default.asp.

Таким образом, попытка прямой загрузки любой страницы нашего приложения без предварительной аутентификации приведет лишь к тому, что в окне браузера появится предложение ввести идентификатор и пароль. Только после успешной аутентификации определяется переменная сеанса с именем Ok и становится возможной работа с другими страницами приложения.

Файл footer.asp (листинг 9-20) просто вставляет в страницу закрывающие теги </BODY> и </HTML>, а также закрывающую фигурную скобку оператора if-else, проверяющего результат аутентификации в файле header.asp.

Листинг 9-20. Вы найдете в файле chap09\LoginTest\footer.asp на прилагаемом к книге компакт-диске

Передача параметров через скрытые поля форм

В предыдущих примерах мы показали, как передавать параметры из одной страницы в другие с использованием переменных сеанса, Cookie и параметров в строке адреса URL страницы. Все эти способы, за исключением последнего, предполагают, что пользователь разрешил в своем браузере использование Cookie. Однако осторожные пользователи могут отказаться от применения Cookie, и тогда приложение будет работать неправильно.

Есть еще один способ передачи параметров между страницами ASP, доступность которого не зависит от параметров браузера пользователя. Этот способ основан на применении скрытых полей в формах.

Рассмотрим конкретный пример.

Пусть в нашем приложении есть три страницы, предназначенные для последовательного выбора некоторых параметров. На первой из них (рис. 9-18) пользователь должен выбрать цвет, размер и указать некоторое слово.

Рис. 9-18. Первая страница, предназначенная для выбора параметров

Выбрав параметры и щелкнув кнопку Дальше >>>, пользователь попадает на вторую страницу (рис. 9-19). Здесь ему нужно ввести свое имя.

Рис. 9-19. Вторая страница, предназначенная для выбора параметров

При помощи кнопки Дальше >>>, расположенной на второй странице, пользователь попадает на последнюю, третью, страницу, отображающую все выбранные ранее параметры (рис. 9-20).

Рис. 9-20. Просмотр выбранных параметров

Обратите внимание, что параметры, указанные в первой и второй странице, были переданы в третью страницу. Чтобы осуществить это, мы применили скрытые поля форм, невидимые на экране.

Рассмотрим исходные тексты приложения.

Первая страница (листинг 9-21) содержит обычную форму с двумя списками и текстовым полем, а также кнопку Дальше >>> типа submit.

<input type="submit" value="Дальше >>>" name="B1"></p>

Здесь пока не использованы никакие скрытые поля.

Листинг 9-21. Вы найдете в файле chap09\Hidden1.html на прилагаемом к книге компакт-диске

Когда Вы щелкнете эту кнопку, данные из формы будут переданы методом POST в страницу hidden2.asp, указанную в параметре ACTION тега <FORM>:

<form method="POST" action="hidden2.asp">

Исходный текст этой страницы представлен в листинге 9-22.

Листинг 9-22. Вы найдете в файле chap09\Hidden2.asp на прилагаемом к книге компакт-диске

На странице hidden2.asp находится форма с однострочным текстовым полем Name, а также три скрытых текстовых поля с именами FavoriteColor, FavoriteSize и KeyWord:

<form method="POST" action="hidden3.asp">
  <table border="0" width="332">
     <tr><td width="171" height="21">
Ваше имя</td>
       <td width="153" height="21">
       <input type="text" name="Name" size="20"></td>
     </tr>
  </table>
  <p><input type="submit" value="
Дальше >>>" name="B1"></p>
  <input type="hidden" value="<%=Request.Form("FavoriteColor")%>" name="FavoriteColor"></p>
  <input type="hidden" value="<%=Request.Form("FavoriteSize")%>" name="FavoriteSize"></p>
  <input type="hidden" value="<%=Request.Form("KeyWord")%>" name="KeyWord"></p>
</form>

Значения этих полей, определяемые параметром value, зависят от данных, принятых из полей формы, расположенной на предыдущей странице. Таким образом, содержимое скрытых полей формы второй страницы зависит от выбора, сделанного пользователем в форме первой страницы.

После того как пользователь щелкнет на второй странице кнопку Дальше >>>, вызывается третья страница hidden3.asp. Ей будут переданы все поля из формы второй страницы, в том числе и скрытые.

Исходный текст третьей страницы представлен в листинге 9-23.

Листинг 9-23. Вы найдете в файле chap09\Hidden3.asp на прилагаемом к книге компакт-диске

Здесь мы просто извлекаем содержимое всех полей формы, расположенных на странице hidden2.asp, и показываем в ячейках таблицы:

<table>
  <tr><td>Любимый цвет</td>
  <td><b><%=Request.Form("FavoriteColor")%></b></td></tr>
  <tr><td>Любимый размер</td>
  <td><b><%=Request.Form("FavoriteSize")%></b></td></tr>
  <tr><td>Волшебное слово</td>
  <td><b><%=Request.Form("KeyWord")%></b></td></tr>
  <tr><td>Ваше имя</td>
  <td><b><%=Request.Form("Name")%></b></td></tr>
</table>

Описанную технику используют и при создании мастеров, упрощающих выполнение различных задач. Так как хорошо спроектированный мастер должен допускать просмотр страниц в обоих направлениях, необходимо предусмотреть соответствующие кнопки, причем располагать их следует в разных формах, так как они будут ссылаться на разные страницы. Серверный сценарий должен обеспечить заполнение скрытых полей этих форм для передачи параметров между страницами как в прямом, так и в обратном направлении.

Отладка сценариев в страницах ASP

Интегрированная среда разработки Microsoft InterDev 6.0 предоставляет отличные средства для отладки не только клиентских, но и серверных сценариев. Без этой возможности разработка сложных приложений ASP была бы очень затруднена.

Если серверный сценарий написан на языке JScript, то для вызова отладчика Вам необходимо вставить в исходный текст сценария оператор debugger (заметим, что недостаточно просто поставить точку останова, нужно вызвать отладчик явным образом).

На рис. 9-21 мы показали процесс отладки одного из серверных сценариев, показанных в этой главе.

Рис. 9-21. Отладка серверного сценария

Отладчик Microsoft InterDev 6.0 позволяет устанавливать дополнительные точки останова, просматривать содержимое переменных и выполнять множество других действий. Подробное описание процесса отладки выходит за рамки нашей книги. Заметим только, что для использования этого отладчика Вам придется настроить соответствующим образом сервер Microsoft Internet Information Server. По умолчанию отладка сценариев отключена, и Вам следует ее включить.

Запустите приложение Microsoft Management Console и откройте панель свойств сервера Web (или отдельного виртуального каталога), выбрав строку Properties из контекстного меню. Щелкните кнопку Configuration на вкладке Virtual Directory, чтобы открыть панель Application Configuration (рис. 9-22).

Рис. 9-22. Панель Application Configuration

Здесь Вам нужно открыть вкладку App Debugging и пометить переключатели Enable ASP server-side script debugging и Enable ASP client-side script debugging. После этого закройте панель и перезагрузите компьютер. Теперь Вы можете приступить к отладке серверных сценариев.

Организация поиска страниц на Вашем узле Web

Если узел Web содержит большое количество статических страниц HTML, возможно, имеет смысл создать поисковую систему. С помощью этой системы посетители узла смогут искать нужную им информацию по ключевым словам.

Пример страницы с поисковой системой, созданной для узла Центра эндохирургии и литотрипсии (http://www.celt.ru) показан на рис. 9-23.

Рис. 9-23. Страница поиска узла http://www.celt.ru

Чтобы выполнить поиск, нужно набрать ключевое слово в поле ПОИСК ПО СЕРВЕРУ, расположенное в верхнем левом углу страницы, а затем щелкнуть кнопку ИСКАТЬ. Результаты поиска будут отображены на отдельной странице, созданной динамически сценарием ASP (рис. 9-24).

Рис. 9-24. Просмотр результатов поиска

Здесь отображаются заголовки первых 10 найденных документов, причем около каждого заголовка звездочками показана степень соответствия содержимого найденной страницы сделанному запросу. В нижней части страницы есть ссылки для просмотра других страниц с результатом запроса.

Заметим, что если основное информационной содержимое узла Web хранится не в статических документах HTML, а в базе данных (это верно, например, для Интернет-магазина http://www.itbook.ru и узла Web издательства «Русская Редакция» http://www.rusedit.ru), то поиск лучше выполнять средствами СУБД. В противном случае посетители будут находить только то, что хранится на статических страницах, а таких страниц на активных узлах Web может быть очень мало.

Если узел Web создан на базе сервера Microsoft Internet Information Server, то для организации поиска удобно использовать стандартный сервис Indexing Service. В следующем разделе мы расскажем о том, как его настроить в среде операционной системы Microsoft Windows 2000 Server.

Настройка сервиса Indexing Service

Прежде всего, Вам нужно запустить приложение Computer Management. Чтобы это сделать, откройте папку Control Panel и щелкните дважды значок Administrative Tools. Затем в раскрывшейся папке нужно дважды щелкнуть значок Computer Management.

В результате этих действий на экране компьютера появится главное окно приложения Computer Management, показанное на рис. 9-25.

Рис. 9-25. Главное окно приложения Computer Management

По умолчанию это приложение работает с локальным компьютером, однако, выбрав из меню Action строку Connect to another computer, можно управлять с его помощью ресурсами удаленного компьютера.

Чтобы добраться до консоли управления сервисом Indexing Service, раскройте папку Services and Applications, дважды щелкнув ее мышью. На рис. 9-25 эта папка показана уже раскрытой.

Щелкнув папку Indexing Service правой клавишей мыши, Вы получите доступ к контекстному меню, управляющему работой соответствующего сервиса. В частности, с помощью строк Start и Stop контекстного меню можно запускать и останавливать сервис Indexing Service.

Создание служебного каталога

Чтобы сервис Indexing Service мог проиндексировать страницы HTML Вашего узла Web, необходимо создать индексный каталог, расположив его на локальном диске сервера Web. В этом каталоге будут созданы файлы индекса.

Для создания каталога остановите сервис Indexing Service, а затем, щелкнув правой клавишей мыши папку Indexing Service, выберите строку New. После этого из меню второго уровня выберите строку Catalog.

В результате на экране появится диалоговое окно создания нового каталога Add Catalog, показанное на рис. 9-26.

Рис. 9-26. Диалоговое окно создания нового каталога Add Catalog

В поле Name введите имя каталога, используя для этого латинские буквы. Имя каталога потребуется серверному сценарию ASP, запускающему поиск и отображающему результаты поиска.

В поле Location необходимо ввести путь к каталогу, в котором сервис Indexing Service расположит служебные файлы индекса. Для упрощения ввода воспользуйтесь кнопкой Browse.

Обращаем Ваше внимание, что в этом поле Вы не должны указывать путь к каталогу с документами HTML, подлежащие индексированию. Поле Location предназначено для ввода пути к служебному каталогу, содержимое которого формируется сервисом Indexing Service автоматически.

Указание пути индексируемой папки

Теперь необходимо указать сервису Indexing Service путь к индексируемой папке с документами HTML. Таких папок может быть создано несколько.

Чтобы это сделать, щелкните правой клавишей мыши папку служебного каталога, созданного на предыдущем этапе, и выберите строку New. После этого из меню второго уровня выберите строку Directory.

На экране появится диалоговое окно Add Directory, показанное на рис. 9-27.

Рис. 9-27. Диалоговое окно Add Directory

Укажите в поле Path путь к папке, содержащей индексируемые страницы HTML, а затем щелкните кнопку OK. Воспользуйтесь для удобства кнопкой Browse.

Теперь Вам нужно запустить сервис Indexing Service, и через некоторое время указанная Вами папка с документами HTML будет проиндексирована.

Подготовка сценария для поиска страниц

Теперь, когда Вы создали каталог и указали папки с документами HTML, подлежащие индексированию, можно заняться серверным сценарием, выполняющим поиск по ключевым словам.

Строго говоря, поиск выполняет не сценарий, а сервис Indexing Service. Что же касается сценария, то он только обращается к этому сервису с помощью интерфейсов соответствующих элементов управления ActiveX, установленных на сервере IIS.

Наш поисковый сценарий использует объекты Query и Utility. Эти объекты используются вместе. Они позволяет определять запросы и запускать их на выполнение.

В листинге 9-24 мы привели исходный текст сценария поиска, созданный компанией Spektrum Web Development для узла http://www.celt.ru. Он составлен на языке VB Script.

Листинг 9-24. Вы найдете в файле chap09\query.asp на прилагаемом к книге компакт-диске

Рассмотрим наиболее интересные фрагменты этого исходного текста.

Прежде всего, сценарий создает объекты Query и Utility для дальнейшего использования в процессе поиска:

set Q = Server.CreateObject("ixsso.Query")
set util = Server.CreateObject("ixsso.Util")

Далее сценарий устанавливает несколько свойств объекта Query:

Q.Query = CompSearch
Q.Columns = "DocTitle, Path, Filename, characterization, rank"
Q.SortBy = "Path[d]"
Q.MaxRecords = 300
Q.LocaleID = 1049
Q.Catalog = "celt"

Эти свойства описаны в табл. 9-2.

Таблица 9-2. Свойства объекта Query

Свойство

Описание

Query

Строка запроса. Составляется на языке запросов сервиса Indexing Service, напоминающего параметры оператора WHERE языка SQL. Эта строка формируется сценарием на базе текстовой строки, введенной пользователем в форме поиска

Columns

Список столбцов, возвращаемых в табличном наборе записей с результатами запроса

SortBy

Строка, содержащая столбцы, по которым выполняется сортировка

MaxRecords

Максимальное количество возвращаемых записей

LocaleID

Идентификатор национального языка

Catalog

Имя каталога, в котором производится поиск

 

Дополнительно сценарий может задать область поиска, добавив ее к объекту Query при помощи метода AddScopeToQuery объекта Util:

util.AddScopeToQuery Q, FormScope, "deep"

Далее сценарий запускает запрос на выполнение, вызывая для этого метод CreateRecordSet объекта Query:

set RS = Q.CreateRecordSet("nonsequential")

После выполнения запроса его результаты можно получить в цикле:   

RecordCount=RS.RecordCount

Do While Not RS.EOF

Leaf=RS("Path")
RankBase=RS("rank")
DocTitle=RS("DocTitle")
characterization=RS("characterization")
 
. . .

RS
.MoveNext
Loop

Количество найденных записей находится в свойстве RS.RecordCount. Его можно использовать для вывода результата поиска на нескольких страницах.

В табл. 9-3 мы привели описание полей набора записей, полученных в результате поиска. Извлекая отдельные поля, можно динамически формировать страницы HTML, отображающие результат поиска. Более подробную информацию об использовании сервиса Indexing Service Вы найдете в MSDN.

Таблица 9-3. Поля набора записей результата поиска

Имя поля

Описание

Path

Полный физический путь к найденному файлу, включая имя файла

Rank

Значение от 0 до 1000, характеризующее насколько «хорошо» данный документ соответствует запросу

DocTitle

Заголовок документа

characterization

Аннотация — содержимое первого параграфа документа.

HitCount

Количество слов в документе, соответствующих запросу

FileName

Имя файла

Работа с файлами

Иногда при создании серверных сценариев ASP возникает необходимость в выполнении тех или иных действий с файлами, расположенными в каталогах сервера Web. В то время как программы CGI и расширения ISAPI могут пользоваться для этого программным интерфейсом операционной системы, серверные сценарии ASP решают эту задачу при помощи элемента управления ActiveX FileSystemObject.

Для чего может пригодиться непосредственная работа Web-приложений с файлами?

В книжном Интернет-магазине ITBOOK.RU каждую ночь запускается сценарий JavaScript, извлекающий из базы данных полный список книг, имеющихся в продаже. Этот список записывается в файл, ссылка на который имеется на одной из страниц узла Web магазина.

Кроме того, в административном приложении, управляющем работой магазина (в приложении Back-офиса), сценарий ASP создает файл с прайс-листом, извлекая название и стоимость книг из базы данных.

Еще одно применение технологии непосредственной работы с файлами из сценариев ASP реализовано в узле Web Центра эндохирургии и литотрипсии http://www.celt.ru. Для того чтобы некоторые разделы этого узла можно было изменять без привлечения опытного Web-дизайнера и программиста, информация для этих разделов готовится в обычных текстовых файлах.

Администратор, сопровождающий этот узел Web, готовит такие файлы при помощи обычного текстового редактора, а затем записывает их в каталоги сервера Web с помощью протокола FTP. Сценарий ASP считывает текстовые файлы и формирует страницы разделов, выполняя необходимое форматирование. Таким способом организованы, в частности, разделы новостей, требующих постоянного обновления.

Как Вы узнаете из 14 и 15 глав нашей книги, административное приложение книжного Интернет-магазина ITBOOK.RU использует более удобную технологию обновления информации через браузер. Эта технология, однако, требует использования сервера базы данных.

Создание объекта FileSystemObject

Чтобы создать соответствующий объект, сценарий ASP должен воспользоваться методом CreateObject объекта Server:

var fso = Server.CreateObject("Scripting.FileSystemObject");

Если же Вы создаете сценарий JavaScript, работающий в пакетном режиме под управлением Windows Scripting Host (WSH) , то этот объект создается следующим образом:

var fso = WScript.CreateObject("Scripting.FileSystemObject");

После того как объект FileSystemObject создан, Вы можете выполнять различные операции с файлами, вызывая его методы.

Учтите, что доступ к файлам осуществляется с правами посетителя сервера Web, которые по умолчанию минимальны. Если приложение должно выполнять запись данных в файлы, проследите за правильной установкой прав доступа на каталог, который содержит такие файлы.

Создание нового файла

Чтобы создать новый файл, Вы должны воспользоваться методом CreateTextFile объекта FileSystemObject:

var BookListDir="c:\\Projects\\download\\booklist.txt";
var f=fso.CreateTextFile(BookListFile, true, false);
if(f==null)
  return;

Первый параметр метода CreateTextFile должен содержать полный путь к создаваемому файлу в виде текстовой строки. В приведенном выше примере мы указали полный путь к файлу со списком книг Интернет-магазина ITBOOK.RU, создаваемому автоматически путем извлечения нужной информации из базы данных.

Второй параметр указывает, нужно ли перезаписывать файл, если файл с таким именем уже существует. Если задать здесь значение true, файл будет перезаписан.

С помощью третьего параметра можно задать формат данных выходного файла. Если в качестве третьего параметра задать константу true, будет создан файл UNICODE, а если false — то файл ANSI.

Заметим, что второй и третий параметр можно не указывать. В этом случае предполагается, что они будут иметь значение false.

В случае успешного создания файла метод CreateTextFile возвращает объект TextStream, который можно использовать для чтения или записи текстовых данных. Мы рассмотрим его ниже. В том случае, когда по каким-то причинам файл создать не удалось, метод CreateTextFile возвращает значение null.

Открытие существующего файла

Чтобы открыть существующий текстовый файл для чтения или записи, необходимо воспользоваться методом OpenTextFile:

var BookListDir="c:\\Projects\\download\\booklist.txt";
mode=1;
var f=fso.OpenTextFile(BookListFile, mode, true, false);
if(f==null)
  return;

Первый параметр метода OpenTextFile должен указывать полный путь к открываемому файлу.

Второй параметр определяет режим, в котором открывается файл. Здесь можно указывать константы 1, 2 и 8. В первом случае файл открывается для чтения, во втором — для записи, а в третьем — для добавления новых данных в конец файла.

Третий параметр указывает, что делать, если файл с таким именем не существует. Если задать здесь значение true, будет создан пустой файл, а если false — возникнет ошибка.

И, наконец, с помощью четвертого параметра можно задать формат данных открываемого файла. Если в качестве третьего параметра задать константу -1, файл будет открыт в режиме UNICODE, если 0 — в режиме ANSI. Если указать здесь значение –2, файл будет открыть в том режиме, который установлен в операционной системе по умолчанию.

В случае успешного открытия файла метод OpenTextFile возвращает объект TextStream, который можно использовать для чтения или записи текстовых данных. В том случае, когда по каким-то причинам файл не удалось открыть, возвращается значение null.

Закрытие файла

После того как Вы завершили работу с файлом, его необходимо закрыть методом close:

f.Close();

Это необходимо для освобождения всех ресурсов, связанных с файлом. Кроме того, если Вы открывали файл для записи, фактическая запись данных и сброс промежуточных буферов может выполняться только после закрытия файла.

Запись в файл

После того как Вы создали новый файл или открыли существующий файл, получив объект TextStream, можно записывать в него новый текст методами Write, WriteLine и WriteBlankLine. Всем этим методам передается один параметр.

Первый из этих методов — метод Write записывает в файл текстовую строку, переданную через единственный параметр.

Метод WriteLine работает аналогично методу Write, но дополнительно записывает в выходной файл символ конца строки.

И, наконец, метод WriteBlankLine записывает в файл столько пустых строк, сколько задано в параметре.

Вот фрагмент программы, формирующей в файле полный список книг Интернет-магазина ITBOOK.RU:

var f=fso.CreateTextFile(BookListFile, true);
if(f==null)
  return;

f.WriteLine("+=================================================+");
f.WriteLine("I   
ПОЛНЫЙ СПИСОК КНИГ МАГАЗИНА ITBOOK.RU        I");
f.WriteLine("+=================================================+");
f.WriteLine("");
f.WriteLine("");

var connect, rs, cmd;
connect = WScript.CreateObject("ADODB.Connection");
connect.ConnectionTimeout = 15;
connect.CommandTimeout = 10;
connect.Open("DSN=RE_DB_DSN", "RR_USER", "user");

cmd = WScript.CreateObject("ADODB.Command");
cmd.CommandText = "select * from PRODUCT_HISTORY where obsolete=0";
cmd.CommandType = adCmdText;
cmd.ActiveConnection = connect;
rs = cmd.Execute();

var i=1;
while(!rs.EOF)
{
  var title=html2txt(rs.Fields("title").value, ReplaceTab);
  var author=html2txt(rs.Fields("author").value, ReplaceTab);
  var isbn=html2txt(rs.Fields("isbn_no").value, ReplaceTab);
  var series=html2txt(getSeriesTitle(rs.Fields("series_id").value), ReplaceTab);
  var pages=rs.Fields("pages").value;
  var pics=rs.Fields("pictures").value;
  var cd=rs.Fields("cd_present").value;
  var published=rs.Fields("publish_year").value;
  var status=rs.Fields("status").value;
  var price=rs.Fields("price").value;
  var comment1=html2txt(rs.Fields("comment1").value, ReplaceTab);
   
  f.Write(i + ". ");
  f.Write("----------------------------------------------------r\n");
  f.Write("     " + title + "\r\n");
  f.Write("        " + author + ", " + published + "
г., " + pages + " стр.");
   
  if(cd!=0)
    f.Write(", CD-ROM");
     
  if(pics!=0)
    f.Write(",
с ил.");
     
  f.Write("\r\n        " + "ISBN: " + isbn);
   
  if(status==1)
  {
    f.Write(" (
подписка " + comment1 + ")");
  }
  else if(status==2)
  {
    f.Write(" (
готовится к изданию " + comment1 + ")");
  }
  else if(status==3)
  {
    f.Write(" (
сдана в типографию " + comment1 + ")");
  }
  else if(status==5)
  {
    f.Write(" (
закончилась " + comment1 + ")");
  }
   
  f.WriteLine("\r\n        " + "
Серия: " + series);
  f.WriteLine("        " + "
Цена: " + price + " руб.");
   
  f.WriteLine("");
  rs.MoveNext(); i++;
}
rs.Close();
connect.Close();

f.Close();

Здесь мы вначале создаем новый текстовый файл и сразу же открываем его методом CreateTextFile. Далее при помощи метода WriteLine в файл записывается заголовок списка книг.

После этого программа открывает таблицу базы данных и извлекает из нее в цикле нужную информацию. Отдельные поля таблицы базы данных комбинируются в текстовые строки, которые затем записываются в файл (использованный здесь способ работы с базой данных будет описан в следующей главе).

Когда формирование файла закончено, он закрывается методом close.

Чтение файла

Для чтения файла предназначены методы Read, ReadLine и ReadAll.

Первый из этих методов — метод Read считывает и возвращает строку символов, размер которой передается ему через единственный параметр.

Метод ReadLine считывает и возвращает одну строку текста, а метод ReadAll — содержимое всего файла.

В примере, приведенном ниже, мы открыли и прочитали в переменную txt содержимое файла booklist.txt:

var BookListDir="c:\\Projects\\download\\booklist.txt";
mode=1;
var f=fso.OpenTextFile(BookListFile, mode, true, false);
if(f==null)
  return;
txt= f.ReadAll();
f.close();

Позиционирование в файле

Программы могут выполнять позиционирование в файлах, открытых с помощью объекта TextStream, аналогично тому, как это делается с обычными функциями потокового ввода и вывода для файлов, предусмотренных в программном интерфейсе операционной системы и библиотеках средств разработки обычных приложений.

В частности, когда программа выполняет запись в файл или читает данные из файла, происходит автоматическое перемещение текущей позиции, начиная с которой происходит запись или чтение. Сразу после открытия файла методом OpenTextFile или создания файла методом CreateTextFile текущая позиция устанавливается на начало файла.

С помощью метода Skip программа может переместить текущую позицию к концу файла на количество символов, заданных этому методу в качестве параметра.

Аналогично, метод SkipLines позволяет переместить текущую позицию к концу файла на заданное количество строк. Количество пропускаемых таким образом строк передается методу SkipLines через единственный параметр.

Удаление файлов

Метод DeleteFile позволяет удалить файл, полный путь которого передается ему в качестве первого параметра:

var fso = Server.CreateObject("Scripting.FileSystemObject");
var BookListDir="c:\\Projects\\download\\booklist.txt";
fso.DeleteFile(BookListDir, true);

Если задать второй параметр метода DeleteFile как true, то файл будет удален даже в том случае, если у него установлен атрибут «Только чтение».

Если файл был создан методом CreateTextFile или открыт методом OpenTextFile, то его можно удалить, вызвав метод DeleteFile для соответствующего объекта TextStream:

var BookListDir="c:\\Projects\\download\\booklist.txt";
mode=1;
var f=fso.OpenTextFile(BookListFile, mode, true, false);
if(f==null)
  return;
else
  f.DeleteFile(true);

Параметр метода, указанный как true, позволяет удалять файлы с атрибутом «Только чтение».

Учтите, что сервер может отложить удаление файла на какое-то время. При этом, несмотря на то, что метод DeleteFile выполнился без ошибок и возвратил управление, файл может существовать еще несколько десятков секунд. Эту особенность следует учитывать при создании собственных программ, удаляющих или переименовывающих файлы.

Копирование файла

С помощью метода CopyFile можно копировать файлы. Этому методу нужно передать три параметра. Первый параметр задает полный путь к исходному файлу, второй — полный путь к каталогу, в который нужно скопировать данный файл. Если задать третий параметр как true, то при копировании существующий файл будет перезаписан.

Вот пример вызова метода CopyFile:

var fso = Server.CreateObject("Scripting.FileSystemObject");
var BookListDir="c:\\Projects\\download\\booklist.txt";
fso. CopyFile(BookListDir, "c:\\Projects\\download\\backup\\");

Перемещение файла

Метод MoveFile позволяет перемещать файл. Ему нужно передать два параметра, первый из которых задает полный путь к исходному файлу, а второй — полный путь к каталогу, в который нужно переместить данный файл:

var fso = Server.CreateObject("Scripting.FileSystemObject");
var BookListDir="c:\\Projects\\download\\booklist.txt";
fso.MoveFile(BookListDir, "c:\\Projects\\download\\old\\");

Проверка существования файла

Метод FileExists позволяет проверить существование файла, полный путь к которому передается методу в качестве параметра:

 

var fso = Server.CreateObject("Scripting.FileSystemObject");
var BookListDir="c:\\Projects\\download\\booklist.txt";
if(fso.FileExists(BookListDir))
  fso.DeleteFile(BookListDir, true);

Здесь проверяется существование файла с именем booklist.txt. Если этот файл существует в каталоге c:\\rojects\download, он удаляется методом DeleteFile.

Обработка ошибок

Используя механизм исключений, сценарий JavaScript может организовать обработку ошибок, возникающих при использовании объектов FileSystemObject и TextStream.

Ниже мы показали использование конструкции try-catch для обработки ошибок, возникающих при создании файла:

var FilePath="c:\\Projects\\download\\price.txt";
try
{
  var PriceFile = fso.CreateTextFile(FilePath, true);
}
catch(ex )
{
  Response.Redirect("default.asp?ERR=BUSY&RND=" + Math.random().toString());
}

Если файл создать не удалось, программа загружает в окно браузера страницу default.asp, передавая ей значение параметра ERR. Вызов метода Math.random необходим для отключения кэширования страниц в браузере.

Использование объекта Dictionary

Серверным сценариям ASP доступен объект Dictionary (словарь), предназначенный для хранения именованных элементов данных. Вы можете добавлять элементы в словарь, определяя для них имя (называемое также ключом) и значение, а также извлекать нужные значения по имени.

В Интернет-магазине ITBOOK.RU мы использовали словарь Dictionary в качестве хранилища товаров, отобранных посетителями магазина в электронную корзину. При этом в качестве ключа выступает идентификатор книги, а в качестве значения — количество приобретенных книг.

Объект Dictionary обладает набором свойств и методов, обеспечивающих выполнение следующих операций:

·         добавление нового элемента (метод Add);

·         проверка существования элемента в словаре (метод Exist);

·         удаление элемента с заданным ключом (метод Remove);

·         удаление всех элементов (метод RemoveAll);

·         установка режима сравнения элементов словаря (метод CompareMode);

·         запись или извлечение элемента по заданному ключу (метод Item);

·         запись или чтение ключа элемента (метод Key);

·         определение количества элементов, хранящихся в словаре (свойство Count);

·         получение массива всех элементов, хранящихся в словаре (свойство Items);

·         получение массива всех ключей элементов, хранящихся в словаре (свойство Keys)

Работу со словарем Dictionary мы продемонстрируем на примере сценариев обслуживания электронной корзины посетителя Интернет-магазина.

Создание объекта Dictionary

Объект Dictionary создается при помощи метода CreateObject, о котором мы рассказывали в предыдущем разделе:

var dic = Server.CreateObject("Scripting.Dictionary");

В Интернет-магазине мы создаем по одному такому объекту для каждого сеанса, инициированного посетителем. Поэтому эта операция выполняется функцией Session_OnStart, определенной в файле global.asa, являющегося неотъемлемой частью любого приложения ASP. Вот сокращенный исходный текст этой функции из проекта Интернет-магазина ITBOOK.RU:

function Session_OnStart()
{
  var basketObj = Server.CreateObject("Scripting.Dictionary");
  basketObj.CompareMode=0;
  Session("Basket")= basketObj;
}

Здесь созданный объект Dictionary сохраняется в переменной сеанса с именем Basket.

Свойство CompareMode хранит режим сравнения, используемый для работы с ключами записей. Если сравнение должно проводиться в двоичном режиме, значение этого свойства должно быть равно 0, а если в текстовом — 1.

Добавление нового элемента

Чтобы добавить новый элемент в словарь, используйте метод Add, передав ему в качестве первого параметра значение ключа, а в качестве второго — данные элемента:

var basketObj=Session("Basket");
basketObj.Add(bookID, bookAmount);

Здесь мы добавили в корзину покупателя bookAmount книг с идентификатором bookID.

Учтите, что в словаре могут храниться только элементы с уникальными ключами, поэтому Вам не удастся добавить в словарь два элемента для одной и той же книги. Позже мы покажем, как решить эту проблему.

Проверка существования элемента

Метод Exist позволяет проверить существование в словаре элемента с заданным ключом. Вы можете использовать этот метод, например, перед добавлением нового элемента с целью проверки существования элемента с таким же ключом:

var basketObj=Session("Basket");
if(!basketObj.Exists(bookID))
  basketObj.Add(bookID, bookAmount);

Здесь добавление нового элемента выполняется только в том случае, если словарь не содержит элемент с таким же ключом, что и у добавляемого элемента.

Получение значения элемента

Чтобы получить значение элемента с заданным ключом, воспользуйтесь методом Item:

var basketObj=Session("Basket");
var total_books = basketObj.Item(bookID);

Здесь мы извлекли и записали в переменную total_books количество книг с идентификатором bookID, отложенных в корзину покупателем Интернет-магазина.

Изменение элемента

Допустим, Вы обнаружили, что покупатель уже отобрал в корзину некоторую книгу, а затем хочет купить еще одну или несколько таких же книг. В этом случае Вам нужно изменить значение элемента, записанного в словарь для этой книги.

Эту операцию можно выполнить при помощи метода Item:

var basketObj=Session("Basket");
basketObj.Item(bookID) = basketObj.Item(bookID) + bookAmount;

Здесь мы вначале извлекли количество первоначально купленных книг с идентификатором bookID, а затем увеличили это количество на bookAmount книг и записали снова в элемент с ключом bookID.

Вот полный фрагмент кода, отвечающий за добавление в корзину покупателя новой книги:

// Идентификатор добавляемой книги
var bookID=Request("BOOKID")(1);

// Количество добавляемых книг с таким идентификатором
var bookAmount=parseInt(Request("AMOUNT")(1),10);

var basketObj=Session("Basket");

if(!basketObj.Exists(bookID))
  basketObj.Add(bookID, bookAmount);
else
  basketObj.Item(bookID) = basketObj.Item(bookID) + bookAmount;

Здесь мы извлекли из полей формы с именами BOOKID и AMOUNT идентификатор добавляемой книги и количество книг, соответственно, и сохранили эти числа в переменных bookID и bookAmount.

Затем мы проверили, не ранится ли в словаре элемент с ключом bookID (то есть, не положил ли покупатель эту книги в корзину ранее). Для проверки использован метод Exists.

Если в корзине такой книги нет, то в словарь добавляется новая запись (методом Add). Если же такая книга уже есть в корзине, то мы изменяем значение элемента описанным выше способом.

Использование объекта Dictionary для перекодировки

Еще одно применение, которое мы нашли для элемента управления Dictionary — табличная замена при перекодировке документов HTML в обычный текст. Такая перекодировка используется в Интернет-магазине ITBOOK.RU для преобразования текстовой информации о книгах, хранящейся в базе данных в виде фрагментов документов HTML, в обычный текст. Этот текст можно пересылать по электронной почте и выводить в текстовые файлы, так как все теги HTML при перекодировке удаляются или заменяются заранее определенной последовательностью символов.

Сразу после запуска сценарий JavaScript создает объект Dictionary описанным выше способом:

var ReplaceTab = WScript.CreateObject("Scripting.Dictionary");

Далее мы добавляем в него элементы в виде пар «ключ-значение»:

ReplaceTab.Add("b","");
ReplaceTab.Add("br","\n");
ReplaceTab.Add("p","\n");
ReplaceTab.Add("hr","\n------------------------------------------------------\n");
ReplaceTab.Add("quot",'"');
ReplaceTab.Add("amp",'&');
ReplaceTab.Add("nbsp",' ');

Роль ключа играет заменяемая строка, а роль значения — последовательность символов для замены. Например, символ b (тег <b>) мы заменяем на пустую строку, а тег разделителя — на строку, состоящую из символов дефиса.

Чтобы перекодировать строку src_html, мы вызываем функцию html2txt, передавая ей в качестве первого параметра исходную строку, а в качестве второго — словарь для перекодировки ReplaceTab:

var dst_txt=html2txt(src_html, ReplaceTab);

Результат перекодировки сохраняется в переменной dst_txt.

Исходный текст функции html2txt приведен ниже:

function html2txt(src, ReplaceTab)
{
  if(src=="" || src==null)
    return "";
   
  var dst="";
  var tag="";
  var replacer;

  for(var i=0; i<src.length; i++)
  {
    if(src.charAt(i) == '<')
    {
      tag="";
      i++;
      for(;i<src.length; i++)
      {
        if(src.charAt(i) != '>')
          tag += src.charAt(i);
        else
          break;
      }
      replacer=ReplaceTab.Item(tag);
     
      if(replacer != null)
        dst += replacer;
      else
        continue;
    }

    else if(src.charAt(i) == '&')
    {
      tag="";
      i++;
      for(;i<src.length; i++)
      {
        if(src.charAt(i) != ';')
          tag += src.charAt(i);
        else
          break;
      }
      replacer=ReplaceTab.Item(tag);
     
      if(replacer != null)
        dst += replacer;
      else
        continue;
    }
    else if(src.charAt(i) == '\n')
    {
      continue;
    }
    else
      dst += src.charAt(i);
  }
  return dst;
}

Вначале функция проверяет исходную строку src. Если она пустая, функция не выполняет никаких действий, кроме возврата пустой строки.

Далее начинается цикл сканирования входной строки с целью поиска тегов HTML. Найденные теги заменяются следующим образом:

replacer=ReplaceTab.Item(tag);

Вы можете использовать функцию html2txt в своих разработках или создать на ее базе собственную функцию перекодировки по словарю.

[Назад] [Содержание] [Дальше]


Создание интернет-магазинов: http://www.shop2you.ru/ © Александр Фролов, Григорий Фролов, 1991-2016