Какой самый простой способ вызвать Http GET URL с помощью Delphi?

37

Там веб-службы, которые я хочу вызвать в своем приложении, я могу использовать его при импорте WSDL или просто использовать "HTTP GET" с URL-адресом и параметрами, поэтому я предпочитаю позже, потому что это простая вещь.

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

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

  • 0
    Как вы думаете, достаточно ли использовать HTTP GET для вызова функции веб-сервиса?
  • 0
    Это если это RESTful веб-сервис.
Показать ещё 2 комментария
Теги:
http
network-programming

8 ответов

24
Лучший ответ

Вы можете использовать API WinINet следующим образом:

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

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

  • 1
    Получение настроек IE "бесплатно" - это только функция, если вы используете IE. :)
  • 0
    Спасибо Ларс, это светлый путь :)
Показать ещё 7 комментариев
29

Вызов веб-службы RESTful с помощью Indy довольно прост.

Добавьте IdHTTP в свой раздел uses. Помните, что 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;
  • 3
    Вопрос был в том, можно ли это сделать без Инди
  • 5
    Вопрос заключался в том, чтобы не добавлять сложный код Indy. Код не сложный.
Показать ещё 8 комментариев
11

На самом деле код в принятом ответе не работал у меня. Поэтому я немного изменил его, так что он фактически возвращает 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. Cheers, Aldis:)

  • 0
    И это работает с HTTPS URL;)
  • 0
    Это работает, только если ответ фактически закодирован в ASCII или UTF-8, что не является гарантией.
7

Если вы можете загрузить файл, вы можете использовать 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;

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

4

Использование HTTP API HTTP также может быть легким.

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;

В приведенном выше коде я подразумеваю, что 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;
  • 1
    Да, это отличное и простое решение, но не забудьте вызвать CoInitialize(nil); и CoUninitialize в начале и конце соответственно.
  • 2
    Это упоминается в ссылках для случая асинхронного потока. Однако в этом конкретном примере объект работает в основном потоке VCL, где COM уже был инициализирован. Полагаю (хотя и не проверял) то же самое верно для LCL в Windows
Показать ещё 6 комментариев
3

В новых версиях 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;
2

Используйте функцию Synapse TCP/IP в модуле HTTPSEND (HTTPGetText, HTTPGetBinary). Он будет тянуть HTTP для вас и не требует каких-либо внешних DLL, кроме Winsock. Последняя версия SVN отлично работает в Delphi 2009. Это использует вызовы функций блокировки, поэтому нет никаких событий для программирования.

Обновление: блоки очень легкие и не основаны на компонентах. Последняя версия SVN отлично работает и в Delphi XE4.

  • 1
    HTTP-вызовы в Indy также блокируются.
1

Если ваше приложение только для Windows, я бы предложил использовать WinSock. Он достаточно прост, позволяет выполнять любой HTTP-запрос, может работать как синхронно, так и асинхронно (используя неблокирующий WSASend/WSARecv с обратными вызовами или добрый старый send/recv в выделенном потоке).

  • 0
    Хотя Winsock может использоваться непосредственно для этого, я не рекомендовал бы это. HTTP - сложный зверь, который можно реализовать с нуля вручную.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню