AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi BDS2006 Download einer Datei vom Webserver mit TClientSocket
Thema durchsuchen
Ansicht
Themen-Optionen

BDS2006 Download einer Datei vom Webserver mit TClientSocket

Ein Thema von cramer · begonnen am 30. Aug 2007 · letzter Beitrag vom 31. Aug 2007
Antwort Antwort
Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
108 Beiträge
 
Delphi 2006 Enterprise
 
#1

BDS2006 Download einer Datei vom Webserver mit TClientSocket

  Alt 30. Aug 2007, 16:08
Hallo,
ich lade in meinem Programm mit TClientSocket eine EXE Datei von einem Webserver.
Bei meinen Test unter Windows XP habe ich festgestellt, das vor den Dateidaten im ersten Block der Header (erster Block 268 Byte) vom Webserver mitgeschickt wird.
Zitat:
HTTP/1.1 200 OK Server: Microsoft-IIS/5.0 X-Powered-By: ASP.NET
Date: Thu, 30 Aug 2007 13:20:58 GMT Content-Type: application/octet-stream
Accept-Ranges: bytes Last-Modified: Thu, 30 Aug 2007 08:14:15 GMT
ETag: "80a5ffc0ddeac71:a19" Content-Length: 1446912
Erst im zweiten Block befindet sich der Anfang der Datei. Also habe ich den ersten Block übergangen und speichere die Datei erst ab dem 2. Block. Klappt super, aber wenn ich einen anderen PC mit Windows2000 nehme,
befinden sich schon im ersten Block(4004 Byte) Teile der Datei.
Im ersten Fall unter XP endet der Header mit 2 x CRLF und dann kommen die Daten, im zweiten Fall stehen 3 x CRLF vor den Daten.
Hat jemand eine Idee, wie man Header und Daten sicher trennt und wie sich z.B. ein Apache Webserver als Gegenstelle verhält ?
Thanks in advance
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.
  Mit Zitat antworten Zitat
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.861 Beiträge
 
Delphi 11 Alexandria
 
#2

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 16:11
Warum verwendest du keine HTTP-Kompos?
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
108 Beiträge
 
Delphi 2006 Enterprise
 
#3

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 16:34
Habe bei Tests mit den unterschiedlichsten Indy Version unter D5 etliche Hänger, kurioses Verhalten und wenig Abwärtskompatibilität zu älteren Versionen festgestellt und daher wenig Vertrauen dazu.
Im Prinzip klappt es ja auch mit der einfachen SocketVersion, wenn man herausfinden könnte, wie die Trennung Header/Daten funktioniert.
Wenn es gar nicht anders geht, muß ich halt den Header nach der Längenangabe parsen, alle Blöcke speichern und am Ende den Header (EmpfangeneDatenMenge - Headerlängenangabe) vom Anfang der Daten löschen.
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#4

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 16:39
1. Du kannst nicht einfach einen Block weglassen weil OnClientRead die Aufrufe teilt. Du kannst dich nicht darauf verlassen - OnClientRead kann beim nächsten Rechner für jedes Zeichen einzelnd aufgerufen werden (übertrieben, aber im Bereich des möglichen) und von daher musst du selber auf die Trennung achten.
2. Wenn keine Indys, dann nutze Windows: InternetOpenURL, InternetDownloadURL, etc.
  Mit Zitat antworten Zitat
Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
108 Beiträge
 
Delphi 2006 Enterprise
 
#5

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 16:47
OK probiere ich mal aus, InternetOpenUrl habe ich ja gefunden aber ? InternetDownloadURL ?
Gehe ich richtig in der Annahme, daß für die o.g. Funktionen aber auch ein Internetexplorer installiert sein muß
und ClientSocket auch ohne IE funktioniert ?
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#6

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 17:10
Ja, aber der IE ist doch standardmässig installiert.

Wenn dich das stört, dann geht die Empfehlung wieder in Richtung Indys...
  Mit Zitat antworten Zitat
Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
108 Beiträge
 
Delphi 2006 Enterprise
 
#7

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 30. Aug 2007, 17:25
Muß er aber nicht bleiben IE Uninstall
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.
  Mit Zitat antworten Zitat
Benutzerbild von cramer
cramer

Registriert seit: 23. Jun 2004
Ort: Velbert (NRW)
108 Beiträge
 
Delphi 2006 Enterprise
 
#8

Re: BDS2006 Download einer Datei vom Webserver mit TClientSo

  Alt 31. Aug 2007, 10:03
Zur Info, ich habe es jetzt durch Parsen und Auswertung der Content-Length gelöst.
Alle bisherigen Tests auf unterschiedlichen PCs und unter W2K Pro/Server und WXP funktionierten ohne Probleme.
Nachfolgend die Testversion der Procedure.
Delphi-Quellcode:
procedure TForm1.DownloadFile(RemoteHost, RemoteFileName, LocalFileName: string; ClientSocket: TClientSocket);
var
  ReturnCode, Header, LenPos, FileSize, ReadSize : Integer;
  s, tmpStr, LocalFileTemp : string;
  szBuffer : array[0..4095] of Char;
  FileIn : TFileStream;
  FileOut : TFileStream;
  FileTmp : TFileStream;
begin
  Form1.tag := 0;
  Memo1.Clear;
  Memo2.Clear;
  Memo3.Clear;
  try
    with ClientSocket do begin
      Host := RemoteHost;
      ClientType := ctBlocking;
      Port := 80;
      try
        Open;
        if RemoteFileName[1] <> '/then begin
           RemoteFileName := '/' + RemoteFileName;
        end;
        { Anfrage senden }
        s := 'GET ' + RemoteFileName + ' HTTP/1.0'#13#10 +
             'Host: ' + Host + #13#10#13#10;
        ReturnCode := Socket.SendBuf(Pointer(s)^, Length(s));
        if ReturnCode > 0 then begin
          { Antwort empfangen }
          header := 0;
          LocalFileTemp := changeFileExt(LocalFileName,'.TMP');
          FileTmp := TFileStream.Create(LocalFileTemp, fmCreate);
          try
            while (ReturnCode > 0) do begin
              FillChar(szBuffer, SizeOf(szBuffer), 0);
              ReturnCode := Socket.ReceiveBuf(szBuffer, SizeOf(szBuffer));
              Memo1.Lines.Add(intToStr(ReturnCode)); // Info Blockgrösse
              if ReturnCode > 0 then begin
                if Header = 0 then begin
                  Header := 1;
                  Memo2.lines.Add(szBuffer); // Info 1. Block
                  Memo3.lines.Add(szBuffer); // Info Daten
                  FileTmp.Write(szBuffer, ReturnCode);
                  ReadSize := ReadSize + ReturnCode;
                end else begin
                  Memo3.lines.Add(szBuffer); // Info Daten
                  FileTmp.Write(szBuffer, ReturnCode);
                  ReadSize := ReadSize + ReturnCode;
                end;
              end;
            end;
          finally
            FileTmp.Free;
          end;
          // Header entfernen
          LenPos := AnsiPos('Content-Length:',Memo2.Text);
          if LenPos > 0 then begin
            tmpStr := trim(copy(Memo3.Text,LenPos,40));
            // Eigene Funktion die einen String/Wert zwischen zwei Trennstrings liefert
            tmpStr := trim(ExtStrT2First('Content-Length:',chr($0D)+chr($0A),tmpStr));
            try
              FileSize := StrToInt(tmpStr);
              FileIn := TFileStream.Create(LocalFileTemp, fmOpenRead);
              try
                FileIn.Seek(ReadSize - FileSize, soFromBeginning);
                ReturnCode := FileIn.Read(szBuffer,4096);
                FileOut := TFileStream.Create(LocalFileName, fmCreate);
                try
                  while ReturnCode > 0 do begin
                    FileOut.Write(szBuffer,ReturnCode);
                    ReturnCode := FileIn.Read(szBuffer,4096);
                  end;
                finally
                  FileOut.Free;
                end;
              finally
                FileIn.Free;
              end;
            except
              Form1.tag := 2003; // Fehler FileSize Auswertung
            end;
            DeleteFile(LocalFileTemp);
          end;
        end else begin
          Form1.tag := 2002;
          Form1.caption := 'Keine Antwort von Server : ' + RemoteHost;
       end;
        Close;
      except
        Form1.tag := 2001;
        Form1.caption := 'Keine Verbindung zum Server : ' + RemoteHost;
      end;
    end;
  finally
    If Form1.Tag < 2000 then Form1.caption := '[' + tmpStr + ']'; // Länge
  end;
end;
Erfahrung ist etwas, daß man erst bekommt, kurz nachdem man es dringend gebraucht hätte.
  Mit Zitat antworten Zitat
Antwort Antwort


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:13 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