Discussion:
Starthilfe in Sachen TIdHTTP
(zu alt für eine Antwort)
Jens Lenge
2012-08-20 13:44:40 UTC
Permalink
Hallo Welt,

ich möchte unter XE2 möglichst "generisch" einen HTTP-Download
durchführen - idealerweise direkt in den Speicher und OS-unabhängig,
damit ein späterer Schritt auf MacOS o. ä. möglich ist.

Tante Google liefert dazu folgende Ansatzpunkte:
- Mein bislang verwendetes WinInet scheidet aus, da fest an Windows+IE
gekoppelt.
- Besser sind die mit XE2 gelieferten Indy-Komponenten, speziell TIdHTTP
in Verbindung mit TMemoryStream. Damit wäre auch ein späterer Schritt
"VCL => Firemonkey" problemlos.

Soweit richtig?

Leider scheint die real existierende Doku zu TIdHTTP recht dürftig
(siehe z. B.
http://docwiki.embarcadero.com/Libraries/en/IdHTTP.TIdHTTP), darum: Wer
kennt ein brauchbares Tutorial oder (noch besser) kann Codebeispiele
beisteuern, wie man geeignet...

a) rausfindet, ob die gewünschte URL erreichbar ist (Internetverbindung
vorhanden, Host erreichbar, URL existiert)?

b) abfragt, wie "groß" der Download ist (SPeicherbedarf)?

c) den eigentlichen Download durchführt (ggf. zwischendurch mit einem
Callback zur Forstschrittsanzeige)?

d) prüft, ob der Download fehlerfrei geklappt hat (oder ggf.
unterbrochen wurde)?
Heinrich Wolf
2012-08-20 15:14:26 UTC
Permalink
Hallo,

unter Windows bin ich von Indy weg hin zu WinInet, weil ich mich nicht mit
den Proxy Einstellungen rumärgern wollte. Indy verwende ich unter Lazarus in
Linux. Die Proxy Einstellungen lese ich dabei unter Gnome mit gconftool-2
und unter KDE mit kreadconfig (Pipe aus shell Befehlen). Die Feinheiten, die
Du fragst, mit denen hab ich mich allerdings nicht beschäftigt. Mit
folgendem Code lese ich eine URL in einen String ohne Fortschrittsanzeige
usw.

Stream := ''; // Das ist kein Stream, sondern ein String
{$ifdef Unix}
Proxy := '';
User := '';
Password := '';
Port := 0;
try
HTTP := tIdHttp.Create(Nil);
except
HTTP := Nil;
end;
if HTTP <> Nil then
try
if GetProxyParams(Proxy, User, Password, Port) then
if (Proxy > '') and (Port <> 0) then
begin
HTTP.ProxyParams.ProxyServer := Proxy;
HTTP.ProxyParams.ProxyPort := Port;
if (User > '') and (Password > '') then
begin
HTTP.ProxyParams.ProxyUsername := User;
HTTP.ProxyParams.ProxyPassword := Password;
end;
end;
Stream := HTTP.Get(Pfad + Datei);
finally
HTTP.free;
end;
{$else}
Inet := InternetOpen('GetHtml', Internet_Open_Type_PreConfig, '', '',
0);
if Inet <> Nil then
begin
d := sizeof(Buffer) - 1;
if InternetCanonicalizeUrl(Pfad + Datei, Buffer, d, 0) then
begin
Buffer[d] := #0;
Url := InternetOpenUrl(Inet, Buffer, Nil, DWord(-1), 0,
0);
if Url <> Nil then
begin
d := 1;
while d > 0 do
if InternetReadFile(Url, @Buffer, sizeof(Buffer) - 1, d)
then
begin
Buffer[d] := #0;
Stream := Stream + Buffer;
end
else
d := 0;
InternetCloseHandle(Url);
end;
end;
InternetCloseHandle(Inet);
end;
{$endif}
Sascha Riepel
2012-08-20 20:24:08 UTC
Permalink
Hallo,

eines vorweg, ich bin kein Indy-Spezialist.

Aber ich versuch mein bestes.:-)
a) rausfindet, ob die gewünschte URL erreichbar ist (Internetverbindung vorhanden, Host erreichbar, URL existiert)?
Dazu hat Marian Aldenhövel vor langer Zeit einen Link gepostet.
Leider finde ich den Artikel nicht auf die schelle. Aber dazu eines Vorweg:
Es gibt keine Möglichkeit, Eindeutig zu prüfen ob man mit dem Internet verbunden ist.
Ich werden morgen den Link suchen und hier wieder Posten.
b) abfragt, wie "groß" der Download ist (Speicherbedarf)?
Dazu kann dir leider nichts sagen, zumindest vor dem Start des Dowmloads.
c) den eigentlichen Download durchführt (ggf. zwischendurch mit einem Callback zur Forstschrittsanzeige)?
Dafür gibt es OnWork. Hierfür wird alles notwenige als Parameter übergeben.
Wenn ich mich richtig erinnere, auch die Dateigröße.
d) prüft, ob der Download fehlerfrei geklappt hat (oder ggf. unterbrochen wurde)?
Das wirst du nicht als Fertige Routine wie etwa: "DownloadKompleteAndHasKorrektSize" bekommen.
Dafür gibt es Ereignisse wie OnWork, OnWorkEnd usw...
Etwas Handarbeit ist immer Notwendig.:-)

Vielleicht hilft dir das weiter.

Gruß Sascha.
Sascha Riepel
2012-08-22 07:45:22 UTC
Permalink
Hallo,
Post by Sascha Riepel
Es gibt keine Möglichkeit, Eindeutig zu prüfen ob man mit dem Internet verbunden ist.
Ich werden morgen den Link suchen und hier wieder Posten.
So, jetzt habe ich endlich den Link wieder gefunden:
http://www.marian-aldenhoevel.de/dojo/internet.html

Gruß Sascha.
Jens Lenge
2012-08-22 22:47:11 UTC
Permalink
Post by Sascha Riepel
http://www.marian-aldenhoevel.de/dojo/internet.html
Nett geschrieben. :)

Als Konsequenz streiche ich hiermit feierlich den entsprechenden Teil
Post by Sascha Riepel
a) rausfindet, ob die gewünschte URL erreichbar ist (Host erreichbar, URL existiert)?
Dabei interessiert nur, ob die gewünschte URLs jetzt gerade abgerufen
werden kann. (Falls nein, spielt der Grund dafür keine Rolle.)

Zumindest das müsste doch prüfbar sein, oder?
Sascha Riepel
2012-08-23 13:11:51 UTC
Permalink
Hallo,
Dabei interessiert nur, ob die gewünschte URLs jetzt gerade abgerufen werden kann. (Falls nein, spielt der Grund dafür
keine Rolle.)
Zumindest das müsste doch prüfbar sein, oder?
Da kann ich leider nicht wirklich weiterhelfen.

Ich habe sowas nur einmal verwendet und da beginne ich eindach den Download.
Wenn ich mich nicht Irre, kam damals eine Fehlermeldung wenn das Ziel nicht erreichbar ist.
Die Fehlermeldung war aussagekräftig genug, dass ich nichts weiter unternommen habe.

Ich weiß, nicht schön und sollte so nicht gemacht werden. Aber eine andere Lösung fand ich
damals leider auch nicht.

Gruß Sascha.
Matthias Hanft
2012-08-23 14:59:07 UTC
Permalink
Als Konsequenz streiche ich hiermit feierlich den entsprechenden Teil meiner Frage und beschränke
Post by Sascha Riepel
a) rausfindet, ob die gewünschte URL erreichbar ist (Host erreichbar, URL existiert)?
Warum nicht einfach wie üblich

try
IdHTTP.Get(myURL)
except
ShowMessage('Geht grad nicht!')
end;

Das holts dann aber auch gleich. Wenn Du erst nachschauen willst:

try
IdHTTP.Head(myURL);
try
IdHTTP.Get(myURL)
except
ShowMessage('Mist, beim Nachschauen gings grad noch!')
end
except
ShowMessage('Geht grad nicht!')
end;

Wobei ich letzteres etwas zweckfrei finde, außer Du willst z.B. dem
User eine Dialogbox präsentieren à la "Sie könnten jetzt wrtlprmft.zip
mit 2,3 GB Größe* herunterladen, wollen Sie? JA/NEIN" oder sowas.

Gruß Matthias.

* aus IdHTTP.Response.ContentLength, nach IdHTTP.Head
Jens Lenge
2012-08-27 21:45:55 UTC
Permalink
Post by Matthias Hanft
Warum nicht einfach wie üblich
[...] IdHTTP.Get(myURL)
Ok, klappt soweit - danke!
Anfängerfrage dazu: Wenn ich das Teil "einfach so" per

IdHTTP := TIdHTTP.Create;

erzeuge und vor dem "Get" auch sonst nichts weiter damit mache, wie wird
dann versucht die Verbindung aufzubauen?
a) Direkt (ohne Proxy)
b) Mit den aktuellen Verbindungs-/Proxy-Settings des Systems (IE)
c) Sonstwie, nämlich: __________
Matthias Hanft
2012-08-28 07:07:19 UTC
Permalink
Post by Jens Lenge
Anfängerfrage dazu: Wenn ich das Teil "einfach so" per
IdHTTP := TIdHTTP.Create;
erzeuge und vor dem "Get" auch sonst nichts weiter damit mache, wie wird dann versucht die
Verbindung aufzubauen?
a) Direkt (ohne Proxy)
Genau so. Wenn Du einen Proxy willst, mußt Du IdHTTP.ProxyParams setzen.
Um die IE-/OS-Einstellungen kümmert sich Delphi nicht.

Wobei meine Aussagen für Delphi 7 gelten (und damit Indy 9 oder 10 - weiß
gar nicht so genau). Ob sich das später mal geändert hat, weiß ich nicht.

Gruß Matthias.

Loading...