• 3.1. FTP

  • 3.2. WinInet

  • 3.3. DrBob FTP

  • 3.4. Web Magic

  • 3.4.1. Счетчик

  • 3.4.2. Гостевая книга

  • 3.4.3. Детектор мертвых ссылок

  • 3.4.4. FTP Upload/Download

  • 3.4.4.1. FTP

  • 3.4.4.2. WinInet

  • 3.4.4.3. DrBob FTP

  • 3.4.4.4.Улучшения?

  • 3.4.5. HTML подсветка синтаксиса

  • 3.5. Улучшения?

  • 3. Microsoft WinInet

    Многое из того, что вы узнали, позволяет вам писать Интернет приложения с помощью Delphi. Особенно с помощью новых средств в Delphi 3 таких как ActiveForms и Web Modules. Но иногда мы хотим сделать, что еще быстрее и проще. Иногда мы просто хотим загрузить файл из Интернета. В терминах Интернета это означает, что мы хотим использовать FTP (file transfer protocol) клиента. И если вы верите мне, то вам не требуется ни какой FTP клиент, но если вы верите мне, то вы можете написать свой…

    3.1. FTP

    Как я сказал во введении, FTP означает File Transfer Protocol, который описан в RFC 959. Модель связи FTP может быть реализована с помощью сокетов, но это более низкоуровневое решение и если вы посмотрите спецификацию, то поймети, что написание программы FTP клиента с нуля не такая уж простая задача. С другой стороны, мы можем использовать NetManage TFTP компонент из Delphi 2.01 (и выше) и C++Builder. Я пробовал использовать этот компонент несколько раз, и нашел его просто глюкавым, особенно для файлов свыше 10 Kb. Я могу понять, почему Microsoft (первый разработчик Internet Solutions Pack) не захотела использовать его и продала затем NetManage, которая тоже не справилась с ним и продала далее фирме NetMasters. Проблема в том, что Internet Solutions Pack – хотя и бесплатный – основан на наборе с ограничениями ActiveX, и каждая компания которая использует его также имеет более лучшее решение (обычно не бесплатно). Поддержка и документация всегда отвратительная…

    Так что же, назад к низкоуровневому программированию? Ни в коем случае. Как всегда на помощь приходит Microsoft

    3.2. WinInet

    Некоторое время назад, Microsoft выпустила WinInet, который ни что иное как промежуточный слой между высоким и нижним уровнем программирования Internet API специально для Win32 программистов. WinInet Является интерфейсом высокого уровня для протоколов нижнего уровня, таких как HTTP и FTP. Использование его действительно просто, и хорошо, что модуль WinInet.PAS с API определениями уже включен в Delphi 2.x и выше!

    Имеется также большой документ, описывающий все детали WinInet API, который может быть найден на сайте Microsoft (но его местонахождение постоянно меняется, так что нужно использовать систему поиска, для загрузки последней версии документа).

    От переводчика: можно взять на моем сайте со страницы http://nps.vnet.ee/internet.html

    3.3. DrBob FTP

    WinInet использует не что, что они назвали Интернет хендл "internet handle" (очень похоже на windows handles), и все api функции или нуждаются или возвращают Интернет хендл. Например, что бы открыть новую WinInet сессию, нам нужно вызвать функцию InternetOpen, которая вернет Интернет хендл, который мы должны использовать до конца сессии (и передавать другим API функциям). Для освобождения хендла, мы всегда должны вызывать функцию InternetCloseHandle (после получения хендла мы можем его использовать, но мы обязаны написать блок try-finally, где должны освободить хендл в разделе finally).

    Для открытия удаленного файла (или URL) в Интернете, мы должны вызвать функцию InternetOpenURL, которая опять вернет нам хендл. Теперь, для загрузки удаленного файла (URL) на нашу локальную машину, нам осталось сделать только некоторое количество вызовов функции InternetReadFile, очень похожей на функцию BlockRead, которая копирует данные из удаленного файла в буфер данных. Мы можем использовать BlockWrite для записи из буфера в локальный файл, и все это с помощью всего лишь трех WinInet функций (четыре, если считать функцию InternetCloseHandle), мы можем написать простую, но очень быструю FTP программу следующим образом:

      program DrBobFTP;

      {$APPTYPE CONSOLE}

      {$I+}

      uses

        Windows, WinInet;


        procedure CopyURL(const URL, OutputFile: String);

        const

          BufferSize = 1024;

        var

          hSession, hURL: HInternet;

          Buffer: Array[0..Pred(BufferSize)] of Byte;

          BufferLength: DWORD;

          f: File;

        begin

          hSession := InternetOpen('DrBob',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);

          try

            hURL := InternetOpenURL(hSession, PChar(URL), nil,0,0,0);

            try

              Assign(f, OutputFile);

              Rewrite(f,1);

              repeat

                InternetReadFile(hURL, @Buffer, BufferSize, BufferLength);

                write('.');

                BlockWrite(f, Buffer, BufferLength)

              until BufferLength = 0;

              Close(f);

              writeln('OK') { if we get here, we succeeded }

            finally

              InternetCloseHandle(hURL)

            end

          finally

            InternetCloseHandle(hSession)

          end

        end;


      begin

        if ParamCount <2 >then

        begin

          writeln('Usage: DrBobFTP URL Filename');

          writeln('Example: DrBobFTP http://www.drbob42.com/ftp/headconv.zip hc.zip')

        end

        else

          CopyURL(ParamStr(1), ParamStr(2))

      end.

    Конечно, для выполнения данной программы мы также обязаны иметь WinInet.DLL, которая также может быть найдена на Microsoft web сайте.

    3.4. Web Magic

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

    Поскольку не каждый использует Client/Server версию Delphi 3, мы используем только "голые кости" (bare bones) технологию, такую как мой модуль DrBobCGI или Microsoft WinInet DLL и модули импорта доступные бесплатно.

    3.4.1. Счетчик

    Счетчик посещений это первое, в чем нуждается популярный web сайт. Меня всегда интересует количество людей посетивших мой сайт. Я всегда заинтересован знать количество людей каждый день. И я всегда заинтересован знать, как выходные и праздники влияют на посещения.

    Для отслеживания количества посетителей я просто создан однострочный файл, назвав его "counter", который содержит количество посещений. Единственная вещь, которая нам требуется, это простая CGI программа, которая читает этот файл, увеличивает на единичку и записывает обратно. Конечно, прекрасно при этом показывать посетителю эту информацию или в виде картинки или в виде простого текстового сообщения.

      {$APPTYPE CONSOLE}

      {$I-}

      var

        f: Text;

        i: Integer;

      begin

        System.Assign(f,'counter');

        reset(f);

        if IOResult = 0 then readln(f,i)

                        else i := 0;

        Inc(i);

        rewrite(f);

        writeln(f,i);

        close(f);

        if IOResult <> 0 then { skip };

        writeln('Content-type: text/html');

        writeln;

        writeln('<HTML>');

        writeln('<BODY>');

        writeln('<CENTER>');

        writeln('You are user <B>',i,'</B> of Dr.Bob''s Delphi Clinic');

        writeln('</CENTER>');

        writeln('</BODY>');

        writeln('</HTML>')

      end.

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

    <HTML>

    <FRAMESET ROWS="64,*">

    <FRAME SRC=http://www.drbob42.com/cgi-bin/hitcount.exe? NAME="Head">

    <FRAME SRC="guest.htm"NAME="Main">

    </FRAMESET>

    </HTML>

    Это очень простое CGI приложение. Оно даже не получает ввода, просто преобразовывает удаленный файл на web сервере и возвращает динамическую страницу. Позвольте теперь сделать фокус на более сложном CGI приложении – таком которое требует ввода данных – например гостевой книге.

    3.4.2. Гостевая книга

    Подлинный CGI пример: приложение – гостевая книга (в котором спрашиваем имя и небольшой комментарий), всего лишь несколько строк на Дельфи.

    Сначала CGI форма:

      <HTML>

      <BODY>

      <H2>Dr.Bob's Guestbook</H2>

      <FORM ACTION="http://www.drbob42.com/cgi-bin/guest.exe" METHOD=POST

      Name: <INPUT TYPE=text NAME=name<BR>

      Comments: <TEXTAREA COLS=42 LINES=4 NAME=comments>

      <P>

      <INPUT TYPE=SUBMIT VALUE="Send Comments to Dr.Bob">

      </FORM>

      </BODY>

      </HTML>

    Теперь консольное (Дельфи) приложение:

      program CGI;

      {$I-}

      {$APPTYPE CONSOLE}

      uses

        DrBobCGI;

      var

        guest: Text;

        Str: String;

      begin

        Assign(guest,'guest'); // assuming that's the guestbook

        Append(guest);

        if IOResult <> 0 then // open new guestbook

        begin

          Rewrite(guest);

          writeln(guest,'<HTML');

          writeln(guest,'<BODY')

        end;

        writeln(guest,'Date: ',DateTimeToStr(Now),'<BR');

        writeln(guest,'Name: ',Value('name'),'<BR');

        writeln(guest,'Comments: ',Value('comments'),'<HR');

        reset(guest);

        writeln('Content-type: text/html');

        writeln;

        while not eof(guest) do // now output guestbook itself

        begin

          readln(guest,Str);

          writeln(Str)

        end;

        close(guest);

        writeln('</BODY');

        writeln('</HTML')

      end.

    Примечание, для того, что бы упростить, мы не используем базу данных для хранения комментариев. Иначе это потребовало установки BDE на web сервере.

    3.4.3. Детектор мертвых ссылок

    Любой серьезный web сайт и его web мастер должны всегда следить за актуальность ссылок. И если обнаружится мертвая ссылка (например другой web сайт прекратил существование), но нет никаких оправданий для внутренних мертвых ссылок. И поэтому я написал простую программу, назвав ее HTMLINKS, которая может сканировать .HTM файлы на их присутствие на локальной машине. (что бы потом загрузить их на сервер). HTM файлы из текущего каталога и всех подкаталогов рекурсивно читаются и проверяются на тег "<A HREF=" или "<FRAME SRC=" . Если страница локальная, то есть без префикса "http://", то файл открывается с использованием относительно пути. Если страница не находится, то мы имеем внутреннюю мертвую ссылку, которая должна быть исправлена!!

    Заметим, что программа игнорирует все "file://", "ftp://", "mailto:", "news:" and ".exe?" значения если они встретятся внутри "HREF" части. Конечно, вы свободны в расширить HTMLINKS для проверки и этих случаев, можно также реализовать проверку и внешних ссылок. Для информации я написал и детектор внешних мертвых ссылок в статье для The Delphi Magazine, подробности можно найти на моем web сайте. Для анализа мертвых локальных ссылок код следующий:

      {$APPTYPE CONSOLE}

      {$I-,H+}

      uses

        SysUtils;

      var

        Path: String;


        procedure CheckHTML(const Path: String);

        var

          SRec: TSearchRec;

          Str: String;

          f: Text;

        begin

          if FindFirst('*.htm', faArchive, SRec) = 0 then

          repeat

            Assign(f,SRec.Name);

            Reset(f);

            if IOResult = 0 then { no error }

            while not eof(f) do

            begin

              readln(f,Str);

              while (Pos('<A HREF="',Str)  0) or

                    (Pos('FRAME SRC="',Str)  0) do

              begin

                if Pos('<A HREF="',Str)  0 then

                  Delete(Str,1,Pos('HREF="',Str)+8-3)

                else

                  Delete(Str,1,Pos('FRAME SRC="',Str)+10);

                if (Pos('#',Str) <> 1) and

                   (Pos('http://',Str) <> 1) and

                   (Pos('mailto:',Str) <> 1) and

                   (Pos('news:',Str) <> 1) and

                   (Pos('ftp://',Str) <> 1) and

                   (Pos('.exe?',Str) = 0) then { skip external links & exe }

                begin

                  if Pos('file:///',Str) = 1 then Delete(Str,1,8);

                  if (Pos('#',Str)  0) and

                     (Pos('#',Str) < Pos('"',Str)) then Str[Pos('#',Str)] := '"';

                  if not FileExists(Copy(Str,1,Pos('"',Str)-1)) then

                    writeln(Path,'\',SRec.Name,': [',Copy(Str,1,Pos('"',Str)-1),']')

                end

              end

            end;

            Close(f);

            if IOResult <> 0 then { skip }

          until FindNext(SRec) <> 0;

          FindClose(SRec);

          // check sub-directories recursively

          if FindFirst('*.*', faDirectory, SRec) = 0 then

          repeat

            if ((SRec.Attr AND faDirectory) = faDirectory) and

                (SRec.Name[1] <> '.') then

            begin

              ChDir(SRec.Name);

              CheckHTML(Path+'\'+SRec.Name);

              ChDir('..')

            end

          until FindNext(SRec) <> 0;

          FindClose(SRec)

        end {CheckHTML};


      begin

        writeln('HTMLinks 4.0 (c) 1997-2000 by Bob Swart (aka Dr.Bob - www.drbob42.com)');

        writeln;

        FileMode := $40;

        GetDir(0,Path);

        CheckHTML(Path)

      end.

    3.4.4. FTP Upload/Download

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

    3.4.4.1. FTP

    Как я сказал во введении, FTP означает File Transfer Protocol, который описан в which RFC 959. Модель связи FTP может быть реализована с помощью сокетов, но это более низкоуровневое решение и если вы посмотрите спецификацию, то поймети, что написание программы FTP клиента с нуля не такая уж простая задача. С другой стороны, мы можем использовать NetManage TFTP компонент из Delphi 2.01 (и выше) и C++Builder. Я пробовал использовать этот компонент несколько раз, и нашел его просто глюкавым, особенно для файлов свыше 10 Kb. Я могу понять, почему Microsoft (первый разработчик Internet Solutions Pack) не захотела использовать его и продала затем NetManage, которая тоже не справилась с ним и продала далее фирме NetMasters. Проблема в том, что Internet Solutions Pack – хотя и бесплатный – основан на наборе с ограничениями ActiveX, и каждая компания которая использует его также имеет более лучшее решение (обычно не бесплатно). Поддержка и документация всегда отвратительная…

    Так что же, назад к низкоуровневому программированию? Ни в коем случае. Как всегда на помощь приходит Microsoft

    3.4.4.2. WinInet

    Некоторое время назад, Microsoft выпустила WinInet, который ни что иное, как промежуточный слой между высоким и нижним уровнем программирования Internet API специально для Win32 программистов. WinInet Является интерфейсом высокого уровня для протоколов нижнего уровня, таких как HTTP и FTP. Использование его действительно просто, и хорошо, что модуль WinInet.PAS с API определениями уже включен в Delphi 2.x и выше!

    Имеется также большой документ, описывающий все детали WinInet API, который может быть найден на сайте Microsoft (но его местонахождение постоянно меняется, так что нужно использовать систему поиска, для загрузки последней версии документа).

    От переводчика: можно взять на моем сайте со страницы http://nps.vnet.ee/internet.html

    3.4.4.3. DrBob FTP

    WinInet использует не что, что они назвали Интернет хендл "internet handle" (очень похоже на windows handles), и все api функции или нуждаются или возвращают Интернет хендл. Например, что бы открыть новую WinInet сессию, нам нужно вызвать функцию InternetOpen, которая вернет Интернет хендл, который мы должны использовать до конца сессии (и передавать другим API функциям). Для освобождения хендла, мы всегда должны вызывать функцию InternetCloseHandle (после получения хендла мы можем его использовать, но мы обязаны написать блок try-finally, где должны освободить хендл в разделе finally).

    Для открытия удаленного файла (или URL) в Интернете, мы должны вызвать функцию InternetOpenURL, которая опять вернет нам хендл. Теперь, для загрузки удаленного файла (URL) на нашу локальную машину, нам осталось сделать только некоторое количество вызовов функции InternetReadFile, очень похожей на функцию BlockRead, которая копирует данные из удаленного файла в буфер данных. Мы можем использовать BlockWrite для записи из буфера в локальный файл, и все это с помощью всего лишь трех WinInet функций (четыре, если считать функцию InternetCloseHandle), мы можем написать простую, но очень быструю FTP программу следующим образом:

    program DrBobFTP;

      {$APPTYPE CONSOLE}

      {$I+}

      uses

        Windows, WinInet;


        procedure CopyURL(const URL, OutputFile: String);

        const

          BufferSize = 1024;

        var

          hSession, hURL: HInternet;

          Buffer: Array[0..Pred(BufferSize)] of Byte;

          BufferLength: DWORD;

          f: File;

        begin

          hSession := InternetOpen('DrBob',INTERNET_OPEN_TYPE_PRECONFIG,nil,nil,0);

          try

            hURL := InternetOpenURL(hSession, PChar(URL), nil,0,0,0);

            try

              Assign(f, OutputFile);

              Rewrite(f,1);

              repeat

                InternetReadFile(hURL, @Buffer, BufferSize, BufferLength);

                write('.');

                BlockWrite(f, Buffer, BufferLength)

              until BufferLength = 0;

              Close(f);

              writeln('OK') { if we get here, we succeeded }

            finally

              InternetCloseHandle(hURL)

            end

          finally

            InternetCloseHandle(hSession)

          end

        end;


      begin

        if ParamCount <2 >then

        begin

          writeln('Usage: DrBobFTP URL Filename');

          writeln('Example: DrBobFTP http://www.drbob42.com/ftp/headconv.zip hc.zip')

        end

        else

          CopyURL(ParamStr(1), ParamStr(2))

      end.

    Конечно, для выполнения данной программы мы также обязаны иметь WinInet.DLL, которая также может быть найдена на Microsoft web сайте.

    3.4.4.4.Улучшения?

    Если вы читали документацию по WinInet, вы заметили что, там есть функция FindFile, так что вы можете сделать обзор удаленных файлов. И базируясь на этой информации, вы можете написать своего web робота, который может загрузить часть a web сайта (например, те файлы, которые изменились после последнего посещения данного сайта). Все автоматически и без GUI (зато быстро). Для информации, Я работал над подобным сортом инструментария, названного мной RobotBob, который наложил свой глаз на Борландовский web сайт, помогая мне отслеживать новости и события по Борландовским средствам разработки…

    3.4.5. HTML подсветка синтаксиса

    И последний инструмент, который я использую ежедневно, это программа HTMLHIGH, используемая для подсветки синтаксиса внутри фрагментов <PRE…</PRE> HTML страниц. Версию, работающую из командной строки можно найти на CD-ROM прилагаемой к моей книге. В данный момент я работаю над версией user-friendly Wizard и хочу написать об этом отдельную статью.

    3.5. Улучшения?

    Если вы читали документацию по WinInet, вы заметили что, там есть функция FindFile, так что вы можете сделать обзор удаленных файлов. И базируясь на этой информации, вы можете написать своего web робота, который может загрузить часть web сайта (например, те файлы, которые изменились после последнего посещения данного сайта). Все автоматически и без GUI (зато быстро).








    Главная | В избранное | Наш E-MAIL | Прислать материал | Нашёл ошибку | Наверх