![]() |
Socket: Bild herunterladen
Hi,
ich möchte via Socket ein Bild herunterladen von einer Homepage. Es interessiert mich einfach wie so etwas funktioniert und wie man es mit Delphi umsetzen könnte. Ich habe einen alten Code auf meienr Platte gefunden. Er konnte früher mal einen Quelltext einer Seite herunterladen. Ich dachte mir, man könnte ihn auch problemlos für Grafiken verwenden, was jedoch leider nicht so geht. Zum Code: Zunächst erstell ich mir eine simple Instanz der Klasse mit dem Host und dem "Link". Link ist vielleicht nicht ganz korrekt, aber das interessiert kaum, denn es handelt sich um alles hinter dem Host. Ich will einfach nur die Grafik ![]()
Delphi-Quellcode:
Es werden in der Connect die Befehle ausgeführt:
Create('www.ndallmeyer.de', 'img/logo.jpg');
Delphi-Quellcode:
Bei "Connection: close" frage ich mich, ob es nicht daran liegen könnte, aber mit einer Keep-Alive-Verbindung brachte es auch keine Grafik auf meine Platte. Ich bekomme nur das als Grafik:
GET /img/logo.jpg HTTP/1.1
Host: [url]www.ndallmeyer.de[/url] Connection: close <LEER> <LEER>
Delphi-Quellcode:
Das ist natürlich nicht mein Ziel, denn relevant sind nur die vier zerquetschten Zeichen. Aber zurück zum Code: Wenn der Client besteht, die Verbindung aufgebaut ist, werden über das Read-Ereignis Daten empfangen - der Debugger zeigt jedoch, dass Read nur einmal ausgeführt wird, danach wird nämlich die Verbindung über OnDisconnect geschlossen - das Bild wird zur Sicherheit (um weitere Fehler zu vermeiden) über eine StringList in die Textdatei gespeichert. (Das wird noch durch Streams abgelöst, da es mir besser gefällt, aber erstmal simpel StringList, lieber erst klein dann groß.)
HTTP/1.1 200 OK
Date: Wed, 18 Nov 2009 20:01:55 GMT Server: Apache/2.2.10 (Linux/SUSE) Last-Modified: Sun, 23 Aug 2009 09:05:27 GMT ETag: "63059c-82da-471cb66fd03c0" Accept-Ranges: bytes Content-Length: 33498 Connection: close Content-Type: image/jpeg ÿØÿà Habt Ihr eine Idee, was ich falsch mache ? Vom Log her entspricht es sehr dem Firefox (dieser sendet noch ein paar Befehle mehr, welche ich auch schon durchprobiert habe, aber leider nichts änderten). Kann man eine Grafik auf diese Weise laden ? Ich dachte mir, wenn es der FF so macht, geht das, aber wer weiß.
Delphi-Quellcode:
type
// Client TClientClass = class constructor Create(aHost, aLink : String); destructor Destroy; override; private Msgs : TRichEdit; Link : String; public Client : TClientSocket; Output : String; procedure Connect(Sender: TObject; Socket: TCustomWinSocket); procedure Disconnect(Sender: TObject; Socket: TCustomWinSocket); procedure Read(Sender: TObject; Socket: TCustomWinSocket); procedure Error(Sender: TObject; Socket: TCustomWinSocket; ErrorEvent: TErrorEvent; var ErrorCode: Integer); end; constructor TClientClass.Create(aHost, aLink : String); begin Link := aLink; Client := TClientSocket.Create(nil); with Client do begin Host := aHost; Service := 'http'; OnConnect := Connect; OnDisconnect := Disconnect; OnRead := Read; OnError := Error; Open; end; end; destructor TClientClass.Destroy; begin if Client <> nil then Client.Close; end; procedure TClientClass.Connect(Sender: TObject; Socket: TCustomWinSocket); begin with Socket do begin SendText('GET /'+Link+' HTTP/1.1' + #13#10); SendText('Host: ' + Client.Host + #13#10); SendText('Connection: close' + #13#10); SendText(#13#10); end; end; procedure TClientClass.Disconnect(Sender: TObject; Socket: TCustomWinSocket); begin Bild(Output); Client.Close; end; procedure TClientClass.Read(Sender: TObject; Socket: TCustomWinSocket); begin Output := Output+Socket.ReceiveText; end; |
Re: Socket: Bild herunterladen
Socket.ReceiveText bricht wohl bei einer #0 (PChar) ab mit Lesen, aber du empfängst ja Binär-Daten. :zwinker:
Außerdem könnte bei diesen Text-Lese-Funktionen auch noch eine Zeichensatzdekodierung statfinden, welche ebenfalls nicht sonderlich gut wäre. - zeilenweise den Text (Header) lesen - und dann ab der ersten Leerzeile, welche übrigens das "Trennzeichen" zwischen Header und Daten darstellt, mußt du dann binär lesen. |
Re: Socket: Bild herunterladen
Ah, und was könnte man alternativ tun ?
Nachtrag: Ok, das würde also beim Übertragen der Daten geschehen. Doch wie realisiert man das mit Sockets ? Mir geht es darum bei den Sockets zu bleiben um es leichter portieren zu können (daher keine Indys welche dies eventuell leichter erledigen). |
Re: Socket: Bild herunterladen
Mal 'ne Frage:
Wie hast'n das obrige Zitat Zitat:
Etwa in einem Memo/RichEdit ausgegeben? Diese hören ja bei #0 auf. Denn also ich es grade mal testete, da hatte ich anscheinend das gesamte Bild im Output-String. :gruebel: Also zumindestens in D7 gibt .ReceiveText alle Daten anscheinend sogar unconvertiert zurück ... auch die 0#. [add]
Delphi-Quellcode:
// Datenanfang suchen:
// Alternativ solange Zeilen rauslesen, bis eine Leerzeile gefunden wird. // Man könnte die gelesenen Zeilen auch gleich rauslöschen // und dann hätte man im String nur noch das Bild drinnen i := Pos(#13#10#13#10, Output) + 4; i2 := Pos(#10#10, Output) + 2; if (i2 > 2) and (i2 < i) then i := i2; if i > 4 then begin // Daten lesen: S := TMemoryStream.Create; S.ReadBuffer(Output[i], Length(Output) - i + 1); S.Position := 0; jpeg.LoadFromStream(S); end; PS: ab Delphi 2009 wirst du massive Probleme bekommen, da dort .ReceiveText Unicode ist und somit vermutlich die Binärdaten zerstört werden. |
Re: Socket: Bild herunterladen
Hm, also der Code endet bei mir in einem Stream-Lesefehler. Rausfinden warum konnte ich nicht. Das Ziel ist doch im Prinzip nichts weiter als den String in einen Stream zu klatschen, dann kann man diesen Stream zum Beispiel abspeichern und genauso auch wieder laden. Aber warum das schiefgeht krieg ich einfach nicht raus.
|
Re: Socket: Bild herunterladen
Jupp, genau das wäre das Vorgehen
> den Datenanteil des String (also ohne den/die Header) in einen Stream rein > und mit diesem Stream könnte man dann machen, was man will Gut, Speichern könnte man den String auch direkt, aber z.B. sowas wie LoadFromString bistet ja keine der Bild-Komponenten. :stupid: Du könntest den Stream mal Speichern, ebenso das runtergeladene Bild und dann Beide binär vergleichen. |
Re: Socket: Bild herunterladen
Ja, aber sollte das nicht sogar Dein Code machen ? Wenn ich mich nicht täusche ist es doch genau das, aber habe eben extrem Ärger mit dem MemoryStream, kann den Fehler einfach kaum rauskriegen, die anderen Threads hier haben mir da leider auch nicht so weitergeholfen.
|
Re: Socket: Bild herunterladen
Theoretisch sollte er es machen, also falls ich mich da nicht irgendwo vertahn hab (ist nicht getetet wurden :oops: )
|
Re: Socket: Bild herunterladen
Hi,
bin nochmal rangegangen. Man könnte den String auch so abspeichern:
Delphi-Quellcode:
Das funktioniert, aber nun ist meine Methode mit dem Copy natürlich unfug. Denn im Gegensatz zum Stream rechnet der in dem Sinne ja nicht Binär. So kriege ich dann nicht perfekt abgetrennte Daten, wie hier der Anfang zeigt:
i := Pos(#13#10#13#10, s)+4;
i2 := Pos(#10#10, s)+2; if (i2 > 2) and (i2 < i) then i := i2; s := Copy(s, i, Length(s)); l := Length(s); Stream.WriteBuffer(l, SizeOf(Integer)); Stream.WriteBuffer(Pointer(s)^, l); Stream.Free;
Code:
Der Kram vor dem "yoya" muss noch weg. Wie könnte man das nun realisieren ?
¯ ÿØÿà
|
Re: Socket: Bild herunterladen
Delphi-Quellcode:
Evtl so? Du wirst übrigens eventuell Probleme bei "chunked"-Transfer haben, aber dein empfangener Header sah nicht danach aus.
Stream := TMemoryStream.Create;
try i := Pos(#13#10#13#10, s) + 4; // Header schnappen Stream.Write(s[i], Length(s) - i); // Ab da alles wegschreiben Stream.SaveToFile('c:\bild.jpg'); // Speichern finally Stream.Free; end; HTH |
Re: Socket: Bild herunterladen
Genau das ist es. Bin manchmal verpeilt, den Memorystream hat himitsu doch schon verwendet. :oops: Danke!
|
Re: Socket: Bild herunterladen
Hups :) hatte ich auch irgendwie übersehen... ist ja auch schon spät.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:26 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz