Какой самый простой способ вызвать Http GET URL с помощью Delphi?
Есть веб-сервисы, которые я хочу вызывать в своем приложении, я могу использовать их с импортом WSDL или просто использовать "HTTP GET" с URL-адресом и параметрами, поэтому я предпочитаю позже, потому что это просто.
Я знаю, что могу использовать indy idhttp.get для выполнения этой работы, но это очень простая вещь, и я не хочу добавлять сложный indy-код в свое приложение.
ОБНОВЛЕНИЕ: извините, если мне неясно, я имел в виду "не добавлять сложный инди-код", что я не хочу добавлять инди-компоненты только для этой простой задачи и предпочитаю более легкий способ для этого.
8 ответов
Вы можете использовать WinINet API следующим образом:
uses WinInet;
function GetUrlContent(const Url: string): string;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
Buffer: array[0..1024] of Char;
BytesRead: dWord;
begin
Result := '';
NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(NetHandle) then
begin
UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
if Assigned(UrlHandle) then
{ UrlHandle valid? Proceed with download }
begin
FillChar(Buffer, SizeOf(Buffer), 0);
repeat
Result := Result + Buffer;
FillChar(Buffer, SizeOf(Buffer), 0);
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
until BytesRead = 0;
InternetCloseHandle(UrlHandle);
end
else
{ UrlHandle is not valid. Raise an exception. }
raise Exception.CreateFmt('Cannot open URL %s', [Url]);
InternetCloseHandle(NetHandle);
end
else
{ NetHandle is not valid. Raise an exception }
raise Exception.Create('Unable to initialize Wininet');
end;
источник: http://www.scalabium.com/faq/dct0080.htm
WinINet API использует те же вещи, что и InternetExplorer, поэтому вы также можете бесплатно получить любые настройки подключения и прокси, установленные InternetExplorer.
Вызов веб-службы RESTful с использованием Indy довольно прост.
Добавьте IdHTTP к вашему предложению использования. Помните, что IdHTTP нуждается в префиксе "HTTP://" в ваших URL.
function GetURLAsString(const aURL: string): string;
var
lHTTP: TIdHTTP;
begin
lHTTP := TIdHTTP.Create;
try
Result := lHTTP.Get(aURL);
finally
lHTTP.Free;
end;
end;
На самом деле код в принятом ответе не работает для меня. Поэтому я немного изменил его, чтобы он возвращал String и изящно закрывал все после выполнения. Пример возвращает полученные данные в виде UTF8String, поэтому он будет хорошо работать как для ASCII, так и для страниц UTF8.
uses WinInet;
function GetUrlContent(const Url: string): UTF8String;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
Buffer: array[0..1023] of byte;
BytesRead: dWord;
StrBuffer: UTF8String;
begin
Result := '';
NetHandle := InternetOpen('Delphi 2009', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(NetHandle) then
try
UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
if Assigned(UrlHandle) then
try
repeat
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead);
Result := Result + StrBuffer;
until BytesRead = 0;
finally
InternetCloseHandle(UrlHandle);
end
else
raise Exception.CreateFmt('Cannot open URL %s', [Url]);
finally
InternetCloseHandle(NetHandle);
end
else
raise Exception.Create('Unable to initialize Wininet');
end;
Надеюсь, это поможет кому-то вроде меня, который искал простой код, как получить содержимое страницы в Delphi. Ура, Алдис:)
В более новых версиях Delphi лучше использовать THTTPClient
от System.Net.HttpClient
Блок, так как он является стандартным и кроссплатформенным. Простой пример
function GetURL(const AURL: string): string;
var
HttpClient: THttpClient;
HttpResponse: IHttpResponse;
begin
HttpClient := THTTPClient.Create;
try
HttpResponse := HttpClient.Get(AURL);
Result := HttpResponse.ContentAsString();
finally
HttpClient.Free;
end;
end;
Если загрузка в файл разрешена, вы можете использовать TDownloadURL из модуля ExtActns. Гораздо проще, чем использовать WinInet напрямую.
procedure TMainForm.DownloadFile(URL: string; Dest: string);
var
dl: TDownloadURL;
begin
dl := TDownloadURL.Create(self);
try
dl.URL := URL;
dl.FileName := Dest;
dl.ExecuteTarget(nil); //this downloads the file
finally
dl.Free;
end;
end;
Также возможно получать уведомления о прогрессе при использовании этого. Просто назначьте обработчик события событию OnDownloadProgress в TDownloadURL.
Использование Windows HTTP API также может быть простым.
procedure TForm1.Button1Click(Sender: TObject);
var http: variant;
begin
http:=createoleobject('WinHttp.WinHttpRequest.5.1');
http.open('GET', 'http://lazarus.freepascal.org', false);
http.send;
showmessage(http.responsetext);
end;
- https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa382925.aspx
- http://forum.lazarus.freepascal.org/index.php?topic=14609.0
- Сохраните файл, загруженный через WinHTTP, на диск, используя Delphi XE
- Как использовать "WinHttp.WinHttpRequest.5.1" асинхронно?
- http://www.delphigroups.info/2/4/217167.html
- https://github.com/fabriciocolombo/delphi-rest-client-api/blob/master/src/HttpConnectionWinHttp.pas
В приведенном выше коде я подразумеваю, что COM уже был инициализирован для основного потока VCL. По сообщениям, это может не всегда иметь место для упрощенных приложений или для приложений LCL. Также это определенно не относится к асинхронной (многопоточной) работе.
Ниже приведен фрагмент реального кода. Примечание - функциональность бонусная. Не требуется работать. Поэтому, пока я делаю запросы, меня не волнует их результат, этот результат игнорируется и сбрасывается.
procedure TfmHaspList.YieldBlinkHTTP(const LED: boolean; const Key_Hardware_ID: cardinal);
var URL: WideString;
begin
URL := 'http://127.0.0.1:1947/action.html?blink' +
IfThen( LED, 'on', 'off') + '=' + IntToStr(Key_Hardware_ID);
TThread.CreateAnonymousThread(
procedure
var Request: OleVariant;
begin
// COM library initialization for the current thread
CoInitialize(nil);
try
// create the WinHttpRequest object instance
Request := CreateOleObject('WinHttp.WinHttpRequest.5.1');
// open HTTP connection with GET method in synchronous mode
Request.Open('GET', URL, False);
// set the User-Agent header value
// Request.SetRequestHeader('User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0');
// sends the HTTP request to the server, the Send method does not return
// until WinHTTP completely receives the response (synchronous mode)
Request.Send;
// // store the response into the field for synchronization
// FResponseText := Request.ResponseText;
// // execute the SynchronizeResult method within the main thread context
// Synchronize(SynchronizeResult);
finally
// release the WinHttpRequest object instance
Request := Unassigned;
// uninitialize COM library with all resources
CoUninitialize;
end;
end
).Start;
end;
Используйте функцию Synapse TCP/IP в модуле HTTPSEND ( HTTPGetText, HTTPGetBinary). Он сделает за вас HTTP-запрос и не требует никаких внешних DLL, кроме Winsock. Последний выпуск SVN прекрасно работает в Delphi 2009. При этом используются блокирующие вызовы функций, поэтому нет событий для программирования.
Обновление: единицы очень легкие и не основаны на компонентах. Последняя версия от SVN прекрасно работает и в Delphi XE4.
Если ваше приложение предназначено только для Windows, я бы предложил использовать WinSock. Это достаточно просто, позволяет выполнять любой HTTP-запрос, может работать как синхронно, так и асинхронно (используя неблокирующую WSASend/WSARecv с обратными вызовами или старый добрый send/recv в выделенном потоке).