AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Socket: Bild herunterladen
Thema durchsuchen
Ansicht
Themen-Optionen

Socket: Bild herunterladen

Ein Thema von Nils_13 · begonnen am 18. Nov 2009 · letzter Beitrag vom 24. Nov 2009
Antwort Antwort
Seite 1 von 2  1 2      
Nils_13

Registriert seit: 15. Nov 2004
2.647 Beiträge
 
#1

Socket: Bild herunterladen

  Alt 18. Nov 2009, 20:22
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 http://www.ndallmeyer.de/img/logo.jpg von meiner Seite herunterladen. Das Protokoll wird auf http in der Create gesetzt, daher fällt bei dem Parameter aHost des Konstruktors das http:// weg. Danach kommt der Pfad und der Dateiname (ohne führendes /, da dies die Klasse schon erledigt). Also hätten wir folgenden Erstellaufruf:
Create('www.ndallmeyer.de', 'img/logo.jpg'); Es werden in der Connect die Befehle ausgeführt:
Delphi-Quellcode:
GET /img/logo.jpg HTTP/1.1
Host: [url]www.ndallmeyer.de[/url]
Connection: close
<LEER>
<LEER>
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:
Delphi-Quellcode:
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

ÿØÿà
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ß.)

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;
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.140 Beiträge
 
Delphi 12 Athens
 
#2

Re: Socket: Bild herunterladen

  Alt 18. Nov 2009, 20:40
Socket.ReceiveText bricht wohl bei einer #0 (PChar) ab mit Lesen, aber du empfängst ja Binär-Daten.
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Nils_13

Registriert seit: 15. Nov 2004
2.647 Beiträge
 
#3

Re: Socket: Bild herunterladen

  Alt 18. Nov 2009, 20:42
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).
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.140 Beiträge
 
Delphi 12 Athens
 
#4

Re: Socket: Bild herunterladen

  Alt 18. Nov 2009, 21:38
Mal 'ne Frage:
Wie hast'n das obrige Zitat
Zitat:
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

ÿØÿà
eigentlich bekommen?

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.
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Nils_13

Registriert seit: 15. Nov 2004
2.647 Beiträge
 
#5

Re: Socket: Bild herunterladen

  Alt 19. Nov 2009, 20:38
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.140 Beiträge
 
Delphi 12 Athens
 
#6

Re: Socket: Bild herunterladen

  Alt 19. Nov 2009, 20:47
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.

Du könntest den Stream mal Speichern,
ebenso das runtergeladene Bild
und dann Beide binär vergleichen.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Nils_13

Registriert seit: 15. Nov 2004
2.647 Beiträge
 
#7

Re: Socket: Bild herunterladen

  Alt 19. Nov 2009, 21:14
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.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.140 Beiträge
 
Delphi 12 Athens
 
#8

Re: Socket: Bild herunterladen

  Alt 19. Nov 2009, 21:18
Theoretisch sollte er es machen, also falls ich mich da nicht irgendwo vertahn hab (ist nicht getetet wurden )
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Nils_13

Registriert seit: 15. Nov 2004
2.647 Beiträge
 
#9

Re: Socket: Bild herunterladen

  Alt 24. Nov 2009, 18:52
Hi,

bin nochmal rangegangen. Man könnte den String auch so abspeichern:
Delphi-Quellcode:
  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;
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:
Code:
¯  ÿØÿà
Der Kram vor dem "yoya" muss noch weg. Wie könnte man das nun realisieren ?
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#10

Re: Socket: Bild herunterladen

  Alt 24. Nov 2009, 19:44
Delphi-Quellcode:
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;
Evtl so? Du wirst übrigens eventuell Probleme bei "chunked"-Transfer haben, aber dein empfangener Header sah nicht danach aus.

HTH
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:20 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz