44

我想在我的应用程序中调用一个 Web 服务,我可以使用它来导入 WSDL,或者只使用带有 URL 和参数的“HTTP GET”,所以我更喜欢后者,因为它很简单。

我知道我可以使用 indy idhttp.get 来完成这项工作,但这是非常简单的事情,我不想将复杂的 indy 代码添加到我的应用程序中。

更新:对不起,如果我不清楚,我的意思是“不要添加复杂的 indy 代码”,我不想为这个简单的任务添加 indy 组件,并且更喜欢更轻松的方式。

4

8 回答 8

35

使用 Indy 调用 RESTful Web 服务非常简单。

将 IdHTTP 添加到您的 uses 子句。请记住,IdHTTP 需要 URL 上的“HTTP://”前缀。

function GetURLAsString(const aURL: string): string;
var
  lHTTP: TIdHTTP;
begin
  lHTTP := TIdHTTP.Create;
  try
    Result := lHTTP.Get(aURL);
  finally
    lHTTP.Free;
  end;
end;
于 2008-11-19T11:13:15.890 回答
27

您可以像这样使用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 设置的任何连接和代理设置。

于 2008-11-19T11:27:46.873 回答
17

实际上接受答案中的代码对我不起作用。所以我对其进行了一些修改,所以它实际上返回 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 中检索页面内容的简单代码的人有所帮助。干杯,阿尔迪斯 :)

于 2011-10-13T20:17:29.520 回答
10

在较新的 Delphi 版本中,最好THTTPClientSystem.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;
于 2016-12-30T17:44:31.780 回答
7

如果可以下载到文件,您可以使用 ExtActns 单元中的 TDownloadURL。比直接使用 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 事件。

于 2010-03-20T12:47:03.320 回答
5

使用 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;

在上面的代码中,我暗示 COM 已经为 VCL 主线程初始化。据报道,简单的应用程序或拼箱应用程序可能并非总是如此。此外,异步(多线程)工作绝对不是这种情况。

下面是运行真实代码的片段。注意 - 功能是额外的。它不需要工作。因此,当我发出请求时,我并不关心他们的结果,结果被忽略并丢弃。

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;
于 2015-12-25T15:48:19.497 回答
2

使用HTTPSEND 单元 ( HTTPGetText, HTTPGetBinary )中的Synapse TCP/IP功能。它将为您执行 HTTP 拉取,并且不需要除 Winsock 之外的任何外部 DLL。最新的 SVN 版本在 Delphi 2009 中运行良好。这使用了阻塞函数调用,因此没有要编程的事件。

更新:这些单位很轻,不是基于组件的。SVN 的最新版本在 Delphi XE4 中也运行良好。

于 2008-11-19T13:44:31.873 回答
0

如果您的应用程序仅适用于 Windows,我建议使用 WinSock。它很简单,允许执行任何 HTTP 请求,可以同步和异步工作(使用带有回调的非阻塞 WSASend/WSARecv 或在专用线程中使用旧的发送/接收)。

于 2013-11-15T18:14:03.600 回答