ASP на блюдечке. Часть 2

ActiveX-компоненты и ASP

If you build it, they will come. If you make it dynamic
(using ASP, ActiveX and this article) they'll come back more often.

Рубен Садоян

Введение

Что же такое Active X? (Небольшое «лирическое» отступление)

А зачем, собственно, применять Active X-технологию в ASP?

С чего начать?

Что для этого понадобится?

Создание и подготовка базы данных

Применение Active X в ASP

Формируем главную страницу (index.asp)

Загружаем файл с HTML-формы

    Форма загрузки (UploadForm.asp)

    (Обработка формы загрузки с помощью ActiveX-компонента Upload2DBS.asp)

Загрузка файлов с помощью ASP и VBScript

    Форма загрузки

    Скрипт-загрузчик

А теперь давайте попробуем сами разработать ActiveX-компонент…

    …с помощью Microsoft Visual Basic 6.0

    … с помощью Microsoft Visual C++ 6.0

Еще несколько слов в защиту C++

Заключение

Введение

В первой статье серии «ASP на блюдечке» («ASP на блюдечке. Часть 1. Построение интерфейса к базе данных», КомпьютерПресс 9 за 2000 год) мы ознакомились с ASP, а также с принципами построения с его помощью простейшего интерфейса к базе данных (газетный сайт со встроенными возможностями его пополнения новыми статьями, снабжаемыми фотографиями непосредственно с самого сайта и без программирования). Теперь я предложу читателям обогатить этот интерфейс возможностями загрузки (upload) HTML-статьи и иллюстрации к ней непосредственно с сайта (то есть с HTML-формы), ведения автоматической статистики посещений, организации показа баннеров, а также методами использования и азами разработки Активных Серверных Компонентов (Active Server Components) для ASP. Статья будет весьма полезна начинающим Web-программистам, профессионалам же достаточно беглого взгляда, чтобы понять принципы и вникнуть в детали работы активных серверных страниц — ASP.

Итак…

Что же такое Active X? (Небольшое «лирическое» отступление)

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

Итак, что же такое COM (Component Object Model) и ActiveX? Чтобы ответить на этот вопрос, зададимся сначала другим: каким образом одна часть программного обеспечения должна получать доступ к сервисам, предоставляемым другой частью? Сегодня ответ на этот вопрос зависит от того, что представляют собой эти части. Например, приложения, скомпонованные с библиотекой, могут пользоваться ее сервисами, вызывая функции из этой библиотеки. Приложение может также использовать сервисы другого — являющегося совершенно отдельным процессом. В данном случае два локальных процесса взаимодействуют посредством некоего механизма связи, который обычно требует определения протокола между этими приложениями (набор сообщений, позволяющий одному приложению выдавать запросы, а другому соответствующим образом отвечать на них). Еще пример: приложение, использующее сервисы операционной системы. Здесь приложение обычно выполняет системные вызовы, обрабатываемые операционной системой. Наконец, приложению могут понадобиться сервисы, предоставляемые программным обеспечением, выполняемым на другой машине, доступ к которой осуществляется по сети. Получить доступ к таким сервисам можно множеством способов, таких как обмен сообщениями с удаленным приложением или вызовы удаленных процедур.

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

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

А зачем, собственно, применять Active X-технологию в ASP?

Применение встраиваемых в ASP ActiveX-компонентов значительно облегчает задачу создания сайтов. Посудите сами: ведь создание громоздких функций, выполняющих сложные вычисления, да и простых подпрограмм гораздо удобнее с помощью известных всем языков программирования, таких как Visual Basic, Delphi или C++, а сгенерированный код (.dll или .ocx) будет работать во много раз быстрее, ведь скомпилированный код модуля выполняется почти мгновенно, в то время как препроцессор ASP формирует HTML-страницу для каждого клиента гораздо дольше. Реализация этих функций средствами самого ASP во многих случаях будет нетривиальна, а в некоторых — попросту невозможна. Кроме того, многие полезные компоненты доступны со стороны так называемых третьих фирм (third-party components), которые зачастую распространяются бесплатно (или почти бесплатно).

Итак, я надеюсь, что эта статья поможет вам научиться применять «чужие» компоненты (third-party components) и разрабатывать свои.

С чего начать?

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

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

Что для этого понадобится?

Для реализации вышеизложенной задачи необходим персональный компьютер с Microsoft Windows NT или Windows 2000 (можно и Workstation или Server), установленный IIS (Internet Information Server), какой-нибудь HTML-редактор (советую использовать Macromedia Dreamweaver), Microsoft Access (версии 95, 97 или 2000) и самый обычный текстовый редактор.

Создание и подготовка базы данных

Для начала нашего первого эксперимента создадим базу данных статей, а для этого:

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

Появляется строка в списке источников данных в вашей системе:

Применение ActiveX в ASP

Мировая компьютерная сеть «кишит» и платными, и бесплатными ActiveX-компонентами. Последний параграф настоящей статьи — попытка перечислить наиболее популярные. Для загрузки файла с HTML-формы советую использовать компонент AspUpload 2.0 Copyright (c) 1998-2000  Persist Software, Inc. (http://www.persits.com/). Компонент платный, но временную одномесячную версию вы сможете найти на нашем CD-ROM.

Формируем главную страницу (index.asp)

…
<!- Определяем таблицу ->
<table BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="710">
<tr>
<td WIDTH="232"><img SRC="Images\Banner.jpg"  height=60 width=232></td>
<td WIDTH="10"></td>
<td WIDTH="468"></td>
</tr>
<tr>
<td BGCOLOR="#000000"><b><font color="#FFFFFF">&nbsp;Today  is:
<!- Отобразим дату ->
<%
D = Date()
D = FormatDateTime(D,2)
Response.Write D
%>
</font></b></td>
<td>&nbsp;</td>
<td></td>
</tr>
 
<!- Линки на основные страницы ->
<tr>
<td BGCOLOR="#FFCC99" valign = top>
<a href="http://localhost/List.asp" class="antiLine">
<b> Show Articles List</b></a><br>
<a href="http://localhost/Search/SearchForm.asp" class="antiLine">
<b>Search for an article</b></a><br>
<a href="http://localhost/Upload/UploadForm.asp" class="antiLine">
<b>Upload an article</b></a><br>
<a href="http://localhost/Signin.asp" class="antiLine">
<b>Signing In</b></a><br>
</td>
<td></td>
<td>
<%
‘ Подключимся к таблице Articles базы данных Articles и откроем ее
Set db = Server.CreateObject("ADODB.Connection")
db.Open "Articles" 
‘ Сформируем SQL запрос и выполним его
sSQL = "SELECT * FROM Articles Where IsTopNew = '1' Order by ID DESC"
Set rs = db.Execute(sSQL)
Display = 0
‘ В цикле будем считывать значения полей и добавлять их в таблицу
Do While NOT Rs.EOF
MainImage = rs.Fields("IFile1").value ‘Имя файла с иллюстрацией к  текущей статье
ShouldDisplay = rs.Fields("IsDImage").value
‘Переменная, определяющая, должна ли иллюстрация отображаться
If NOT rs.EOF and Display = 0 and MainImage <> "No" and  ShouldDisplay = "1" Then
Display = 1 ‘ Если да, то сгенерировать соответствующий тэг с именем иллюстрации
Response.Write "<img SRC=" & "Articles\" &  MainImage & " height=300 width=468>"
End If
Rs.MoveNext
Loop
%>
</td>
</tr>
<%
Set rs = db.Execute(sSQL)
Cnt = 0
Do While NOT Rs.EOF
%>

<tr>
<td BGCOLOR="#FFCC99">&nbsp;</td>
<td></td>
 
<td>
<%
If rs.Fields("Article").value <> "No Text" Then ‘Если  поле текста статьи не равно "No Text"
Link = "<a href= http://localhost/ArtTempl.asp?id=" & rs.Fields("ID").value & ">" & rs.Fields("Title").value & "</a>"
Else ‘В противном случае сгенерировать линк на HTML-файл со статьей
Link = "<a href= http://localhost/Articles/" & rs.Fields("TextFile").value & ">" & rs.Fields("Title").value & "</a>"
End If
 
Response.Write Link & "<br>"
‘ Добавляем автора статьи
Response.Write "<i>By " & rs.Fields("Author").value  & "</i><br>"
 
‘ Добавляем аннотацию к статье
ANN = rs.Fields("Annotation").value
If ANN <> "NA" Then
Response.Write ANN
End If
%>
<hr NOSHADE WIDTH="100%">
</td>
</tr>
<%
Rs.MoveNext
Cnt = Cnt + 1
Loop
 
db.Close
Set db = Nothing
%>
</table>
…

 

Следует обратить особое внимание на формирование переменной «Link». В первом случае, когда значение поля «Article» не равно «No Text», ссылка на статью формируется из файла шаблона ArtTempl.asp, которому идентификатор текущей статьи передается в качестве параметра

Link ="<a href= http://localhost/ArtTempl.asp?id="&rs.Fields("ID").value&">"&rs.Fields("Title").value &"</a>"

(дальнейшая обработка в теле файла шаблона подробно обсуждалась в первой части настоящей статьи).

В противном случае ссылка на статью формируется из имени файла (которое содержится в переменной TextFile) с ее HTML-версией, который уже подгружен на сервер и располагается в каталоге «Articles».

Link ="<a href= http://localhost/Articles/" &rs.Fields("TextFile").value &">"& rs.Fields("Title").value &"</a>"

Загружаем файл с HTML-формы

Форма загрузки (UploadForm.asp)

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

Хочется обратить особое внимание на обработку «радиокнопки», определяющей тип статьи («горячая» — «не горячая») и флажок показа иллюстрации на главной странице. Если читатель знаком с первой статьей, то он, вероятно, вспомнит, что в целях обучения вся обработка формы (проверка корректности ввода полей и первоначальная обработка введенных значений) велась на ASP. Приведенный ниже пример иллюстрирует то, как это на самом деле следует делать с помощью какого-либо языка описания сценариев (в нашем случае JavaScript).

В нашем случае мы будем определять состояние флажка показа иллюстрации с помощью небольшого скрипта на JavaScript и «спрятанного» (hidden) поля. Последнее будет принимать значение, соответствующее состоянию флажка.

< script >
function preprocess ()
{
message = 2;
if (mainform.DI.checked) message = 1;
else message = 2;
mainform.details.value = message;
}
</script>

Как видно, значение поля «details» будет равно 1, если флажок поля «DI» был установлен, и 2 — в противном случае. Вызов самого скрипта удобнее всего выполнять по событию «onsubmit», которое обрабатывается по нажатию на кнопку «Submit», и вплоть до передачи управления скрипту-реакции. Таким образом, на этапе ввода можно осуществлять инициализацию внутренних полей и переменных формы, причем непосредственно на стороне клиента (как известно, языки описания скриптов JavaScript и VBScript именно для этого и предназначены). В нашем случае фрагмент формы будет выглядеть следующим образом:

…
<form name="mainform" method="post" enctype="multipart/form-data"
action="http://localhost/Upload/Upload2DBS.asp" onsubmit="preprocess();">
…
<input type="radio" name="IsTopNewSelector" value="0"  checked> <b> Ordinary type Article
<input type="radio" name="IsTopNewSelector" value="1">  Top New type Article</b>
…
<b>Display image on Home page
<input type="checkbox" name="DI" value="0">
<input type="hidden" name="details">
<i>(only for Top News type articles) </i></b>
…
</form>
…

Соответственно радиокнопка «IsTopNewSelector» будет возвращать значение «0» для обычной и значение «1» для «горячей» статьи.

Обработка формы загрузки с помощью ActiveX-компонента Upload2DBS.asp

Работать с ActiveX-компонентами в ASP достаточно просто. Например, загрузка файлов при помощи компонента «ASPUpload» производится всего двумя строчками кода:

<%
Set Upload = Server.CreateObject("Persits.Upload.1") ‘Создаем переменную  — указатель на интерфейс Upload
 Count = Upload.Save ("c:\InetPub\wwwroot\Articles") ‘ Вызываем функцию  Save этого интерфейса
 ‘ И присваиваем переменной Count число подгруженных файлов
%>

Фактически после отработки этих двух строк все файлы, которые были указаны в полях формы, загружаются на сервер — в данном случае в каталог "c:\InetPub\wwwroot\Articles".

Далее необходимо произвести обработку остальных полей формы и добавить запись в базу данных:

…
<%
I = 0
FileI = "No"
Set FI = Upload.Files("IFile1") ‘ Определяем указатель на погруженный  файл
 If Not FI Is Nothing Then ‘ И если он не пуст
 FileI = FI.Path ‘ То читаем полный путь к подгруженному файлу
 strPosition = Instr(25,FileI,"\") ‘ Вырезаем из полного пути собственно  имя файла
intStringLen=strPosition-1
strLeft = Left(FileI,intStringLen)
strRight = Right(FileI,(Len(FileI)-Len(strLeft)-1))
FileI = strRight ‘ И присваиваем его переменной FileI
End If
…

Аналогичные действия должны быть выполнены и с файлом HTML (если таковой был указан)

Set TF = Upload.Files("TextFile")
If Not TF Is Nothing Then
FileT = TF.Path
strPosition = Instr(25,FileT,"\")
intStringLen=strPosition-1
strLeft = Left(FileT,intStringLen)
strRight = Right(FileT,(Len(FileT)-Len(strLeft)-1))
FileT = strRight ‘ И присваиваем его переменной FileТ
End If
ErrA = 0 ‘ Заводим четыре флажка для обработки ошибок ввода полей
ErrT = 0
ErrP = 0
ErrC = 0
‘ Получаем значение флажка показа иллюстрации
DI = Upload.Form("DETAILS")
If DI = 1 Then
IsDisplayImage = "1"
End If
If DI = 2 Then
IsDisplayImage = "0"
End If
‘ Получаем значение поля автора статьи
AUT = Upload.Form("Author")
If AUT = "" Then ErrA = 1 End If
AUT = FormatStr(AUT)
‘ Получаем значение поля заголовка статьи
TIT = Upload.Form("Title")
If TIT = "" Then ErrT = 1 End If
TIT = FormatStr(TIT)
‘ Получаем значение поля текста самой статьи
ART = Upload.Form("Article")
If ART = "" Then
ART = "No Text" ‘ Если оно пусто, присваиваем переменной константу  "No Text"
If File1 = "No" Then
ErrC = 1
End If
End If
‘ Форматируем текст самой статьи для его последующего показа в формате HTML  ART = FormatStr(ART)
 ‘ Получаем значение селектора рубрик SBJ = Upload.Form("Subject")
IsTopNew = Upload.Form("IsTopNewSelector")
ANN = Upload.Form("Annotation")
ANN = FormatStr(ANN)
If ANN = "" Then
ANN = "NA"
End If
‘ Получаем значение поля пароля доступа к базе данных Password = Upload.Form("Password")
If Password = DBP Then
If ErrA = 0 and ErrT = 0 Then
 
‘ Открываем базу данных и записываем в нее значения
Set db = Server.CreateObject("ADODB.Connection")
db.Open "DSN=Articles;UID=sa;PWD=;"
sSQL = "insert into 
Articles(Author,Title,Article,Subject,TextFile,IFile1,Published,IsTopNew,Annotation,IsDImage)values('" & AUT &
 "', '" & TIT & "','" & ART & "','" & SBJ & "','" & FileT & "','" & FileI & "','" & TIM &"','" & IsTopNew &"','" & 
ANN & "','" & IsDisplayImage &"')"
Set rs = db.Execute(sSQL)
db.Close
Set db = Nothing
End If
Else
ErrP = 1
End If
%>
…