2008-11-19 13 views
36

Jest kilka usług internetowych, które chcę wywoływać w mojej aplikacji, mogę ich używać z importowaniem WSDL lub po prostu użyć "HTTP GET" z adresem URL i parametrami, więc wolę później, ponieważ jest to proste.Jaki jest najprostszy sposób wywoływania adresu URL GET Http za pomocą Delphi?

Wiem, że mogę użyć indy idhttp.get, aby wykonać zadanie, ale jest to bardzo proste i nie chcę dodawać złożonego kodu indeksu do mojej aplikacji.

UPDATE: Przepraszam, że nie było jasne, mam na myśli „nie dodawać skomplikowanego kodu indy”, że nie chcę dodawać komponenty Indy tylko dla tego prostego zadania i wolą bardziej lżejszą drogę do tego.

+0

Czy uważasz, że samo użycie HTTP GET wystarczy do wywołania funkcji usługi sieciowej? – Serguzest

+0

Jest to usługa internetowa RESTful. –

+0

Nie wiedziałem, że REST może mieć wsdl też – Serguzest

Odpowiedz

24

Mogłeś użyć WinINet API takiego:

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; 

źródło: http://www.scalabium.com/faq/dct0080.htm

WinINet API wykorzystuje te same rzeczy InternetExplorer korzysta więc można również uzyskać wszelkie ustawienia połączenia i serwera proxy ustawione przez InternetExplorer za darmo.

+1

Ustawienie IE "za darmo" jest tylko funkcją, jeśli używasz IE. :) –

+0

Dzięki Lars, to jest podświetlona droga :) –

+1

Bruce mówi, że gdybyś miał źle skonfigurowany IE, aby użyć ustawienia proxy, które jest wyłączone, na przykład, zostaniesz również uwięziony. Niewyraźne i frustrujące, jeśli tak się stało. –

29

Wywołanie usługi internetowej RESTful przy użyciu Indy jest całkiem proste.

Dodaj IdHTTP do klauzul uses. Pamiętaj, że IdHTTP potrzebuje prefiksu "HTTP: //" na swoich URL-ach.

function GetURLAsString(const aURL: string): string; 
var 
    lHTTP: TIdHTTP; 
begin 
    lHTTP := TIdHTTP.Create; 
    try 
    Result := lHTTP.Get(aURL); 
    finally 
    lHTTP.Free; 
    end; 
end; 
+3

Pytanie było, czy to można to zrobić bez indy –

+4

Pytanie brzmiało, by nie dodawać skomplikowanego kodu Indy. Kod nie jest złożony. –

+0

Bruce, Lars ma rację, powiedziałem w moich pytaniach, że nie chcę używać indyt "idhttp.get", to najprostszy sposób, ale chciałem zapaloną drogę :) –

2

Użyj funkcji Synapse TCP/IP w urządzeniu HTTPSEND (HTTPGetText, HTTPGetBinary). Wykona dla ciebie polecenie HTTP i nie wymaga żadnych zewnętrznych bibliotek DLL innych niż Winsock. Najnowsza wersja SVN działa doskonale w Delphi 2009. Wykorzystuje ona blokujące wywołania funkcji, więc nie ma zdarzeń do zaprogramowania.

Aktualizacja: Urządzenia są bardzo lekkie i nie są oparte na komponentach. Najnowsza wersja SVN działa również doskonale w Delphi XE4.

+1

Połączenia HTTP w Indy również się blokują. –

7

Jeśli można pobrać do pliku, można użyć TDownloadURL z jednostki ExtActns. Znacznie prostsze niż bezpośrednie korzystanie z 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; 

Możliwe jest również otrzymywanie powiadomień o postępie podczas korzystania z tego. Wystarczy przypisać procedurę obsługi zdarzenia do zdarzenia OnDownloadProgress TDownloadURL.

11

Właściwie kod w zaakceptowanej odpowiedzi nie działa dla mnie. Więc trochę go zmodyfikowałem, więc faktycznie zwraca String i z wdziękiem zamyka wszystko po wykonaniu. Przykład zwraca pobrane dane jako UTF8String, więc będzie dobrze działać zarówno dla stron ASCII, jak i dla 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; 

Nadzieja pomaga dla kogoś takiego jak ja, kto szuka łatwego kodu jak pobrać zawartości strony w Delphi. Pozdrawiam, Aldis :)

+0

Działa z adresami URL HTTPS;) – Beny

1

Jeśli twoja aplikacja jest przeznaczona tylko dla systemu Windows, proponuję użyć WinSock. Jest to dość proste, pozwala na wykonanie dowolnego żądania HTTP, może pracować zarówno synchronicznie, jak i asynchronicznie (przy użyciu nie blokującego się WSASend/WSARecv z oddzwonieniem lub dobrym starym wysyłaniem/odbieraniem w dedykowanym wątku).

4

Korzystanie z interfejsu API Windows HTTP może być również łatwe.

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; 

W powyższym kodzie sugeruję, że COM został już zainicjowany dla głównego wątku VCL. Podobno nie zawsze tak jest w przypadku uproszczonych aplikacji lub aplikacji LCL. Z pewnością nie byłoby tak w przypadku pracy asynchronicznej (wielowątkowej).

Poniżej znajduje się wycinek z rzeczywistego uruchomionego kodu. Uwaga - funkcja jest premią. Nie wymaga się pracy. Tak więc, podczas gdy ja wysyłam wnioski, nie dbam o ich wyniki, wynik jest ignorowany i porzucany.

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

Tak, jest to doskonałe i proste rozwiązanie, ale nie zapomnij nazwać "CoInitialize (zero);" i "CoUninitialize" odpowiednio na początku i na końcu. – supersan

+2

Jest to wspomniane w odnośnikach do przypadku asynchronicznego wątku. W tym konkretnym przykładzie obiekt działa w głównym wątku VCL, w którym już zainicjowano COM. Przypuszczam, że (choć nie sprawdziłem) to samo dotyczy LCL na Windows –

+0

Być może ktoś powinien wspomnieć o obiekcie TJvURLGrabber również z JediVCL ... –

3

W nowszych wersjach Delphi lepiej jest użyć THTTPClient z System.Net.HttpClient jednostki, ponieważ jest to standardowe i cross-platform. Prostym przykładem jest

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; 
Powiązane problemy