Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Сокровищница
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  02:46[Войти] | [Зарегистрироваться]

Компонент THTTPGet

Петр Смирнов
дата публикации 01-06-2014 10:48

Для Delphi существует немало компонентов, предназначенных для работы со стандартным HTTP протоколом:

  • устаревшие NetMasters (ссылка ведёт не на официальный сайт, который на момент написания статьи не отвечал, а на статью по их использованию);
  • встроенная в Delphi "индейка" Indy;
  • описанные на Королевстве Internet Component Suite;
  • чуть менее популярный Synapse;
  • для особых любителей, можно использовать даже встроенный в систему и экспортированный в Delphi WebBrowser (если кто захочет сравнить использование WebBrowser для закачки страниц с хранением констант в невидимом TMemo, то спешу его разочаровать — парсинг скриптов, которым испещрены все современные сайты — дело неблагодарное и пусть лучше этим занимается тот, кому это привычно);
  • для любителей BDSM — рекомендую начать со статьи Антона Григорьева про стандартные сокеты, продолжить чтение про сокеты Windows, потом вычитать RFC и получать данные от сервера прямо на сокетах.

Эти компоненты умеют очень многое, не только простую загрузку с HTTP/HTTPS, но и работу с FTP, SMTP, POP3 и рядом других протоколов. Но во многих программах требуется всего лишь использовать загрузку и парсинг страниц и файлов с HTTP/HTTPS серверов. И поддержка "лишних" функций совершенно не планируется (я, конечно, понимаю фанатов, которые будут пытаться реализовать абсолютно абстрагированную от источника данных программу, но не стоит упорствовать, поверьте) то вполне хорошим решением будет использование функций работы с HTTP (которыми, кстати, пользуется сам WebBrowser) под названием WinInet.

Документацию по WinInet можно найти как на языке оригинала — MSDN, так и на русском. Разумеется, и там и там описания будут даны на С++. Если поискать, то можно найти десятки несвязных примеров использования WinInet в проектах Delphi. Они оформлены просто как куски кода, а потому об их реиспользовании даже не идёт речь. Порывшись на Torry, мне удалось найти немало прилично оформленных модулей, упрощающих использование WinInet. Откинув все коммерческие и shareware (странно платить за то, что уже оплачено покупкой Windows и Delphi и то, что ожидается в комплекте с этими продуктами), особенно хочется отметить оформленные в виде компонентов:

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

Разумеется, через некоторое время мне стало "не хватать" тех возможностей, которые предлагал мне компонент "из коробки". А поскольку исходные коды были доступны, то я принялся дорабатывать его под свои нужды. В первую очередь, это коснулось того, что компонент получил возможность отправлять POST запросы, а также добавлять дополнительные поля в запрос. Компонент перестал виснуть при работе из консольного приложения. Ну и ещё несколько косметических изменений. Именно доработанный компонент я и предлагаю Вашему вниманию. Ничего необычного он не предлагает, но для меня его использование оказалось проще, чем использование навороченных Indy или Synapse.

Достоинства

  • отсутствие необходимости делать что либо, чтобы программа заработала через HTTPS. Для настройки Indy на работу с HTTPS потребуется применить немалый бубен (во всяком случае, по одной и той же инструкции я смог без особенного труда настроить работу с HTTPS, а мой знакомый так и не получил необходимого результата, несмотря на мою помощь через TeamViewer).
  • отсутствие самой возможности DLL Hell при работе с сайтами по HTTPS протоколу. Неоднократно сталкивался с проблемой, когда программы, использующие Indy или Synapse на компьютерах других пользователей начинали баловать. Баловства иногда проходили, если в папку с моей программой сложить скачанный OpenSSL, иногда не проходили. Ни в одном из случаев детально разбираться у меня не было желания, так что прокомментировать более подробно про эту особенность Indy и Synapse я не могу. Тем не менее, WinInet умудряется работать и на таких машинах без единого нарекания. То есть — абсолютно нормально. Считаю за плюс.
  • безнастроечная работа через корпоративный прокси-сервер с авторизацией по NTLM. Синапс этот прокси не осилил. При работе с Indy потребовалось вводить пароль от аккаунта. А при использовании HTTPGet не потребовалось даже указывать, что соединение происходит через прокси! Настройки, сделанные в Internet Explorer подцепились автоматом.
  • элементарный парсинг полученной веб-страницы через регулярные выражения одной командой: if R.Exec(HTTPGet.GetStringSync) then ... Никаких временных TMemoryStream, TStringStream, чтобы получить поток с данными, как это было в индейке и синапсе.
  • компактность в консольных приложениях — используя директиву условной компиляции CONSOLE. Она автоматически устанавливается при задании {%APPTYPE CONSOLE}. Я проверял эту функцию на Delphi 2006: создавал приложение, загружающее фиксированный URL. Скорость исполнения была абсолютно идентична, а вот размер отличался: 114 кб для VCL режима и 53,5 кб — для консольного режима. Может быть, кому-то покажется, что это абсолютно бесполезная возможность, но я нередко пишу простые утилиты и мне греет сердце тот факт, что маленькая утилита командной строки, умеющая закачивать по расписанию программу телепередач с какого-нибудь сайта, "весит" 80-100 килобайт, а не мегабайт с хвостом (ага, я про исполняемые файлы Lazarus).
  • возможность авторизации на сайтах без знания логина и пароля, если вход на сайт был ранее выполнен через Internet Explorer. Хотя это можно отнести и к минусам. Я узнал, что существует определённая категория пользователей, столь сильно ненавидящая "осла", что просто они отказались бы пользоваться программой, если бы в ней была предусмотрена возможность авторизации на сайте с помощью авторизации через Internet Explorer. Причина сего странного поведения и иррациональной неприязни к несчастному творению копыт разработчика популярной операционной системы мне осталась непонятной. Не отношу эту "фичу" к минусам программы, так как Вы можете использовать эту особенность функционирования компонента, а можете запрашивать логин и пароль для входа самостоятельно.

Недостатки

  • Некоторые антивирусы фиксируют заражение вирусом вида TR/Dldr.Delphi.Gen. Так, возьмём для примера программу, неимеющую видимых окон (включая консоль). Готовый пример исходного кода TestHidden.dpr можно взять в архиве по ссылке в конце страницы. Почему так происходит? Скорее всего, так будет если не использовать конкретно этот компонент, вообще при использовании функций WinInet в приложении без интерфейса. Как бы антивирус должна насторожить активность приложения, обращающегося к интернету, но не информирующего об этом пользователя. Оно и понятно — у нас, чай, не андроид, где плеер может отправить платное СМС сообщение, не спросив разрешения. Так что при использовании компонента принимайте во внимание этот факт.
  • Нет возможности сперва получить заголовки, а потом только тело. Например, получить ContentDisposition и в зависимости от него сформировать FileName, куда должен сохраняться файл (или спросить в этот момент у пользователя решения, продолжив загрузку в потоке, как это делает большинство браузеров). Возможно, когда-нибудь будет реализовано, но пока не приходит адекватный алгоритм решения проблемы. Свойство OnHeader?
  • Собственно, об этом уже говорилось — ничего такого, что бы не предлагали другие компоненты, это решение не предлагает. Ни большей скорости, ни какого-то особенного удобства в использовании. Да, данный компонент имеет много больший функционал, чем оригинал. Но те же индейки его "переплёвывают" хотя бы по количеству протоколов. Я использую его во всех программах исключительно потому что это "мой велосипед" и мне он нравится, как минимум — компактность. Но это сугубое ИМХО.
  • Иногда свойство компонента генерировать компактную версию (с директивой Console) не срабатывает и приходится явно прописывать эту директиву.

Свойства

В таблице используются обозначения:

  • RW — Read/Write, свойство доступно для записи и чтения;
  • RO — Read Only, свойство доступно только для чтения;
  • Если в поле "Описание" встречается подпись "Оригинальное описание", значит, это свойство унаследовано от оригинального компонента.
ВидимостьНазваниеТипУмолчаниеДоступОписание (оригинальное описание)
Отладочные свойства
publicRawHeadersstringпустоRO "Сырые" заголовки, без разбора, пришедшие от сервера. Поскольку запрос этого параметра занимает некоторое время, он по умолчанию отключён. Включается с помощью параметра DebugMode. При выключенном DebugMode всегда возвращает пустую строку
publicDebugModebooleanfalseRW Включает режим получения "сырых" заголовков. Это чуточку замедляет работу компонента. К тому же, сырые заголовки практически никогда не требуются (мне потребовались только раз в жизни, для чего я и ввёл этот параметр).
Конфигурация компонента
publishedTimeoutinteger30000RW Используется при выполнении запросов с ожиданием потока. Если время работы потока превысит указанное значение — то поток будет аварийно остановлен, а сам процесс загрузки остановится с этой ошибкой. При работе без ожидания потока, либо в полностью синхронном режиме таймаут не используется.
publishedWaitThreadbooleanfalseRW Если включено, то попытка выполнения асинхронных функций GetFile и GetString остановит выполнение процедуры, дожидаясь окончания загрузки. При этом можно не пользоваться событиями, а вычитывать данные прямо из ResultString, или скачанного файла. Для консольного варианта исполнения, свойство включено. Но в консольной программе имеет смысл вообще использовать синхронные GetFileSync и GetStringSync. Они не порождают ненужных потоков.
publishedKeepAlivebooleantrueRW Добавляет заголовок Keep-Alive в отправляемые на сервер данные. Поскольку протокол HTTP 1.1, используемый в компоненте, подразумевает, что соединение будет "постоянным", а большинство серверов это поддерживают, я вообще не вижу смысла отключать этот параметр. Правда, есть такая "особенность" этого постоянного соединения, что иногда возникает ошибка "Соединение с сервером было сброшено". Отключение Keep-Alive помогает этого избежать, но значительно замедляет соединение — так, для пачки файлов размером 300-400 байт, время на получение удваивается.
publishedConnectionTypeTConnectionTypectAutoRW Устанавливает тип используемого интернет-соединения:
ctDirect — использует прямое подключение, без прокси
ctAuto — использует настройки соединения как у Internet Explorer
ctAutoNoINS — использует настройки соединения как у Internet Explorer, но пропускает загрузочные Microsoft JScript и скрипты настройки интернета (это перевод официальной страницы, он мне кажется кривым, у кого есть идеи лучше— предлагайте).
ctProxy — принудительное использование прокси (см. свойства, начинающиеся на Proxy...)
publishedProxyBypassstringпустоRW Перечисляет список серверов, или IP адресов, обращения к которым не должно производиться через прокси-сервер даже если ConnectionType=ctProxy. Этот список может содержать маски. Обращение к адресам localhost, loopback, 127.0.0.1, ::1 всегда выполняется напрямую, так как большинство прокси-серверов неправильно обрабатывают обращения с таким адресом.
PS: В документации не указано, как именно нужно перечислять список серверов в данном списке: через пробел, запятую, точку с запятой и т.д. Эксперимент показал, что список можно писать через запятую.
publishedProxystringпустоRW Указывает прокси-сервер для соединения ctProxy. Практика показала, что для ctAuto и ctAutoNoINS прокси не всегда корректно цепляется, так что есть подозрение, что прокси при его наличии надо указывать всегда.
publishedProxyPortinteger8080RW Порт для прокси сервера
publishedProxyUserstringпустоRW Если прокси требует авторизацию, укажите здесь имя пользователя. Если используется NTLM аутентификация, то ничего указывать не надо — всё и так будет работать. Это ключевой момент, крайне важный для меня. С NTLM аутентификацией многие другие компоненты адекватно не работает. Если имя пользователя не указано, аутентификация не импользуется.
publishedProxyPasswordstringпустоRW Соответственно, пароль для того пользователя, который используется для авторизации на прокси. Несмотря на то, что свойство я сделал published, я считаю достаточно странным хранить здесь пароль, лучше всё-таки воспользоваться защищённым хранилищем.
publishedUserNamestringпустоRW Имя пользователя, используемого HTTP аутентификации. Никакой связи с прокси-аутентификацией! Если не указан — HTTP аутентификация не производится.
Оригинальное описание:
Set this properties if you trying to get data from password protected directories.
publishedPasswordstringпустоПароль пользователя, используемый для HTTP аутентификации.
publishedAgentstringMozilla/4.0...RW Идентификатор клиента пользователя. Нужен крайне редко, по умолчанию в 99% справляется
Оригинальное описание:
User Agent
publishedRefererstringпустоRW Здесь хранится URL предыдущей загруженной страницы.
Оригинальное описание:
Additional data about referer document
publishedAddHeaderstringпустоRW Дополнительные заголовки, которые можно отправить с запросом. Пример: X-Requested-With: XMLHttpRequest (имитация запроса от XMLHttpRequest) или DNT: 1 (просьба сайт не сохранять информацию о пользователе... впрочем, все сайты эту просьбу игнорируют).
publishedAcceptTypesstring*/*RW Какие типы (в соответстии с RFC) хочет принимать приложение. По умолчанию — всё, что отправит сервер.
publishedBinaryDatastringtrueRW Трактует передаваемые сервером данные как двоичный поток. На самом деле, просто пытается узнать размер данных ДО их реального получения. Многие сервера генерируют такой заголовок и для HTML страниц и даже для динамически генерируемых страниц. Если эта настройка отключена, будет неправильно работать OnProgress. Необходимости в отключении этой настройки я не вижу.
Оригинальное описание:
This setting specifies which type of data will taken from the web. If you set this property TRUE then component will determinee the size of files *before* getting them from the web.
If this property is FALSE then as we do not knows the file size the OnProgress event will doesn't work. Also please remember that is you set this property as TRUE you will not capable to get from the web ASCII data and ofter got OnError event.
publishedUseCachebooleanfalseRW Указывает, что запрашиваемые данные можно взять из кеша Internet Explorer.
Оригинальное описание:
Get file from the Internet Explorer's cache if requested file is cached.
publishedPostQuerystringпустоRW Выполняет POST запрос с указанными данными. Разумеется, данные должны быть правильно URLEncodнуты, иначе всё может закончиться плачевно. Заголовок application/x-www-form-urlencoded добавляется автоматически.
publishedFileNamestringпустоRW Указывает путь к локальному файлу, куда будут сохранены данные, если был выполнен запрос с использованием GetFileSync или GetFile. Если это свойство не задать, попытка закачки с помощью GetFile или GetFileSync не выполнится.
Оригинальное описание:
Path to local file to store the data taken from the web
publishedURLstringпустоRW URL, который надо скачать. Не должен быть пустым при выполнении любого метода.
Оригинальное описание:
The url to file or document
publishedTaginteger0RW Классика — просто числовое поле, где Вы можете хранить что угодно.
Полученная информация
publicReadybooleantrueRO Показывает готовность компонента к новой загрузке. Если false — значит, компонент производит загрузку. Обычно, не имеет смысла проверять эту переменную — по окончанию работы автоматически сработает либо OnError, либо OnDoneFile или OnDoneString.
publicResultStringstringпустоRO После выполнения методов GetString, GetStringSync, RunSync(false), RunAsync(false) содержит полученные с сервера данные в виде строки. Во всех остальных случаях — пустая строка. Передаётся в качестве параметра в обработчики OnDoneString, OnDoneStringProc, потому данное свойство полезно только в случае синхронных запросов без использования специализированного обработчика.
publicErrorMessagestringпустоRO Содержит описание, отданное операционной системой при возникновении любых ошибок. Также эта строка передаётся в обработчик OnError, OnErrorProc, потому данное свойсво полезно только в случае синхронных запросов без использования специализированного обработчика. Для унификации, все сообщения англоязычные.
publicErrorCodeinteger0RO Содержит код ошибки, возвращаемые операционной системой, или одно из предопределённых в модуле значений:
HTTPGET_TIMEOUT — время работы потока загрузки превысило значение, указанное в поле Timeout
HTTPGET_NOTSTARTED — ошибка возникает, если не удалось стартовать поток (хендл от BeginThread=0). Мне никогда не встречалась
HTTPGET_FILENOTCREATED — GetFile или GetFileSync не смогли создать файл, указанный в свойсте FileName. Скорее всего, файл уже существует, или папка, куда вы хотите загрузить файл, недоступна для записи текущему пользователю.
HTTPGET_USERREQUEST — поток был завершён процедурой Abort
HTTPGET_BADRESPONSE — одно или несколько полей, переданных сервером, не опознаны. Например, код HTTP запроса (обычно — 200) принял нечисловое значение. Ни с одним из серверов, с которыми я работал, такой ошибки не появлялось.
Это значение передаётся в обработчик OnError, OnErrorProc, потому данное свойсво полезно только в случае синхронных запросов без использования специализированного обработчика.
publicCookiestringпустоRO Осталось в наследство от старого компонента. Отдаёт полученные куки. Вызывает метод GetCookie('');
Оригинальное описание:
Cookies, that you want to send to host. After processing, there will be cookies, sent by host. Now, Expires, Domain, Path and secure cookie options didn't stored.
publicContentDispositionstringпустоRO Возвращаемая сервером строка, описывающая, какое имя и содержимое у присланного файла. Сам компонент игнорирует данное свойство, то есть ВСЕГДА сохраняет файл по тому имени, которое задано в свойстве FileName, так что после закачки приложение самостоятельно (если в этом возникает необходимость) должно проверить это свойство и переименовать закачанный файл в соответствии с указаниями от сервера. Строка не парсится. Обычно, она имеет вид attachment; filename="fname.ext" и легко разбирается на части регулярным выражением. Также в ответе может присутствовать размер файла — выведите отладочное сообщение при написании программы, чтобы понять, какой реально вид у этого заголовка для сервера, с которым Вы работаете.
publicResponseCodecardinal200RO Возвращённый в соответствии с RFC результат

Свойства

Здесь перечислены две группы свойств. Они абсолютно идентичны и вызываются одновременно, если заданы и то и другое. Но для VCL компонентов привычнее писать обработчики в объектно-ориентированном виде (то бишь при работе в дизайнере компонентов). Для консольного приложения (кому как, ИМХО) более привычны обычные процедуры, а то и вообще синхронный режим работы.

НазваниеПрототипОписание
Свойства, предназначенные для VCL приложений (published)
OnProgressprocedure(Sender: TObject; TotalSize, Readed: Integer) of object; Выполняется при закачке очередной порции данных.
Sender — THTTPGet, отправивший сообщение. Крайне полезно в многопоточной конфигурации.
TotalSize — сколько данных предстоит получить. При выключенном BinaryData будет равен всегда 0.
Readed — сколько данных уже получено
OnDoneFileprocedure(Sender: TObject; const FileName: String; FileSize: Integer) of object; Выполняется по окончанию загрузки файла. Файл при этом уже отпущен компонентом и может быть использован (например, переименован в соответствии с командой от сервера).
Sender — THTTPGet, отправивший сообщение. Крайне полезно в многопоточной конфигурации.
FileName — то же, что и FileName компонента
FileSize — размер принятого файла
OnDoneStringprocedure(Sender: TObject; const Result: String) of object; Выполняется по окончанию загрузки строки.
Sender — THTTPGet, отправивший сообщение. Крайне полезно в многопоточной конфигурации.
Result — то же, что ResultString компонента.
OnErrorprocedure(Sender: TObject; const Error: String; Code: integer) of object; Выполняется при ошибке. Если это событие произошло, то ни OnDoneFile ни OnDoneString выполнены не будут. При ошибке, можно попытаться интерпретировать содержимое ResultString или недокачанного файла (автоматически он не удаляется, его надо удалять руками).
Sender — THTTPGet, отправивший сообщение. Крайне полезно в многопоточной конфигурации. Внимательно следите, не вызвана ли ошибка отменой закачки по команде пользователя, чтобы случайно не стартовать новую закачку!
Error — сообщение об ошибке на русском языке в кодировке CP-1251 (для VCL)
Code — код ошибки. Требуется, если необходимо локализовать приложение
Свойства, предназначенные для консольных приложений (public)
OnProgressProcprocedure(Sender: TObject; TotalSize, Readed: Integer) Выполняется при закачке очередной порции данных. Полный аналог OnProgress, но является обычной процедурой.
OnDoneFileProcprocedure(Sender: TObject; const FileName: String; FileSize: Integer); Выполняется по окончанию загрузки файла. Полный аналог OnDoneFileProc, но является обычной процедурой.
OnDoneStringProcprocedure(Sender: TObject; const Result: String); Выполняется по окончанию загрузки строки. Полный аналог OnDoneString, но является обычной процедурой.
OnErrorProcprocedure(Sender: TObject; const Error: String; Code: integer); Выполняется при ошибке. Полный аналог OnError, но является обычной процедурой, а также сообщение об ошибке поступает в OEM кодировке, а не в ANSI (для непосредственного вывода на консоль).

Методы

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

ПрототипОписание
constructor Create(aOwner: TComponent=nil); Создаёт объект. Для консольного варианта можно явно не указывать несуществующего владельца.
destructor Destroy; Без комментариев
function SetCookie(const Name,Value:string):boolean; Устанавливает в Internet Explorer указанную куку
function GetCookie(const Name:string):string; Читает указанную куку из Internet Explorer. Если указать пустое имя — будут прочитаны все куки для соответствующего URL.
procedure Abort; Отменяет асинхронную загрузку. Это приводит к появлению ошибки!
Оригинальное описание:
Stop the current session
Асинхронные методы — выполняются в отдельном потоке
function GetFile:boolean; Для совместимости со приложениями, заточенными на оригинального THTTPGet оставлена старая GetFile. На самом деле, она просто вызывает RunAsync(true);
Оригинальное описание:
Get the file from the web specified in the URL property and store it to the file specified in the FileName property
function GetString:boolean; Для совместимости с приложениями, заточенными на использование оригинального THTTPGet оставлен старый GetString. На самом деле, просто вызывает RunAsync(false);
Оригинальное описание:
Get the data from web and return it as usual String. You can receive this string hooking the OnDoneString event.
function RunASync(const ToFile:boolean):boolean; Загружает данные в отдельном потоке. Если установлен параметр WaitThread, то выход из функции будет осуществлён только после окончания загрузки данных, в этом случае возаращаемое значение true говорит о том, что закачка завершена успешно (используйте ResultString или файл с именем FileName, чтобы получить запрашиваемую информацию), а false — что произошла некоторая ошибка (используйте ErrorCode и ErrorMessage для уточнения).
Если ToFile установлен, то закачка производится в файл с указанным именем, в противном случае — в ResultString
Если WaitThread сброшен, то выход из функции производится немедленно, при этом возвращаемый результат true говорит лишь о том, что поток был успешно запущен, а false — что поток запущен не был. Наиболее вероятная проблема в данном случае — потом ранее был запущен и сейчас ведёт скачивание другой информации.
Учтите, что использовать одновременно синхронные и асинхронные обращения нельзя, работать так они не будут. Выберите заранее тот режим, который Вам нужен. Лично я считаю, что синхронные методы надо использовать в консольных приложениях, а асинхронные — в VCL приложениях.
Синхронные методы — выполняются в вызывающем потоке
function GetFileSync:boolean; Аналог GetFile со включённым WaitThread, но выполняется без выделения в отдельный поток. На самом деле, просто вызывает RunSync(true);
function GetStringSync:string; Аналог GetString со включённым WaitThread, но выполняется без выделения в отдельный поток. На самом деле, просто вызывает RunSync(false);
function RunSync(const ToFile:boolean):boolean; Загружает данные в том потоке, из которого производится вызов, без порождения отдельного потока. Это приводит к тому, что не работает свойство Timeout, защищающее от зависания, не в полной мере отрабатывает Abort.
Если ToFile установлен, то закачка производится в файл с указанным именем, в противном случае — в ResultString
Всестороннего тестирования синхронных методов в VCL приложениях не проводилось. Есть подозрение, что при использовании в главном потоке, будут проблемы (поток останется замороженным на всё время работы компонента). Также при использовании обработчиков событий, могут появляться проблемы, связанные с тем, что вызовы обработчиков выболняются без использования Synchronize, что (к сожалению, лишь периодически) будет приводить к различным проблемам при использовании VCL компонентов из таковых обработчиков.

Установка компонента

На самом деле, ничего не мешает использовать этот компонент как простой хелпер-класс вроде TStringList, создавая его прямо в процедуре/методе и тут же его разрушая. Но для адекватного использования асинхронного метода, всё-таки лучше воспользоваться средствами, предлагаемыми Delphi. Для этого откройте (или создайте) любую библиотеку компонентов (обычно я не мудрствую лукаво и использую стандартную dclusr.dpk), добавить туда .pas файл и нажать кнопку "Install". Если всё нормально, компонент будет установлен в среду и будет доступен на вкладке UtilMind (по историческим причинам). Как пользоваться палитрой компонентов, я надеюсь, учить Вас не нужно.

Примеры использования

Сами исполняемые файлы я не прикладывал. Причина описана выше в разделе Недостатки.

  1. Скрытое тестовое приложение. Единственный файл — TestHidden.dpr. Всё, что делает — загружает главную страницу нашего сайта DelphiKingdom. В конце выводится два MessageBox, показывающие конец загрузки данных и конец работы программы. Особенности поведения скомпилированной версии этой программы описаны в разделе Недостатки.
  2. Консольное тестовое приложение. Единственный файл — TestConsole.dpr. Всё, что делает — загружает главную страницу нашего сайта DelphiKingdom. В процессе выводится прогресс выполнения работы, в конце запрашивается нажатие "Ввод". Данные сохраняются в файл index.htm (по умолчанию). В зависимости от того, был ли залогинен пользователь в Internet Explorer, получим либо незалогиненную версию сайта, либо уже залогиненную. Особенности поведения скомпилированной версии этой программы описаны в разделе Недостатки.
  3. Стандартное VCL приложение. Три файла: проекта TestUpdater.dpr, формы TestUpdate.dfm и исходник формы TestUpdate.pas. Для успешной компиляции, требуется установить компонент в среду Delphi. Что делает эта программа? Есть такая игра — OSU!. Я в неё никогда не играл, но по просьбе одного человека набросал программу для скачивания файлов с этого ресурса. Суть заключается в том, что качать можно только в том случае, если пользователь залогинен на сайте. Так что программа имеет две кнопки и два поля ввода:
    • Первая кнопка проверяет, залогинен ли пользователь на сайте и если нет — открывает в Internet Explorer сайт и предлагает там залогиниться. Если проверка на логин прошла успешно, то разрешается вторая кнопка.
    • Вторая кнопка начинает массовую закачку файлов по ссылкам, положенным во втором поле ввода. Закачка однопоточная, но ничего не мешает сделать несколько компонентов, "привязать" к ним компоненты отображения состояния типа TProgressBar и радоваться жизни.
    • Первое поле ввода — протокол, куда сыплются сообщения о всех удачных/неудачных закачках, а также состояние проверки логина. Нередактируемое.
    • Второе поле ввода — поле для ввода ссылок для закачки. По умолчанию, там лежит пара первых попавшихся ссылок.

Постскриптум

Надеюсь, что компонент Вам понравится. Плюсы и минусы перечислены, примеры использования есть, описания свойств и методов имеются. Что же ещё я забыл? Ах да! Самое главное! Архив с компонентом и примерами прилагается к статье.

Я решил не раскладывать всё по папкам... и так всё достаточно очевидно. Пишите в комментариях, какие изменения стоит внести в компонент. Надеюсь на конструктивную критику. Всегда Ваш

Python aka SmiSoft.



К материалу прилагаются файлы:


Смотрите также материалы по темам:


 Обсуждение материала [ 07-06-2014 14:03 ] 9 сообщений
  
Время на сайте: GMT минус 5 часов

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

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования