![]() |
Indy Http Download+Fortschritt als Funktion geht nicht
Hallo erstmal.
Ich habe ein Problem mit diesem Beispiel ![]() Ich wollte jetzt nicht den Library Eintrag mit Fragen vollspammen. Wenn ich aus dem Source der Beim Button-OnClick ausgeführt wird eine neue Prozedur mache und diese dann mit einem Button zweimal hintereinander ausführe bekomm ich immmer einen ReadTimeout vom idHttp. Wenn ich allerdings nur eine Datei zum Download angebe und dann zweimal auf den Button klicke, geht es... Sieht vielleicht jemand wo das Problem liegt? Tut mir Leid wegen dem riesigen Source-Block, aber man kann ja zur Not auch auf "Zusammenfalten" klicken :wink: Hier der Source:
Delphi-Quellcode:
Schonmal danke für die Hilfe.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP; type THaupt = class(TForm) IdHTTP: TIdHTTP; Status: TLabel; SpeedLabel: TLabel; Progress: TProgressBar; Button1: TButton; procedure IdHTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); procedure IdHTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); procedure Download(AFile :String); procedure Button1Click(Sender: TObject); private { Private-Deklarationen } FTime: Longword; //Beide Variablen werden für die kb/sec anzeige gebraucht FBytes: Longword; // --"-- public { Public-Deklarationen } end; var Haupt: THaupt; const cFileSplitSize : Int64 = 40*1024; //40 KB größe stücke wird die Datei zerhackt URL = 'Http://IrgendWoImNetz/'; implementation {$R *.dfm} function GetSizeName(const Size : int64): String; begin Result := 'Fehler'; if Size = -1 then exit; if Size < 1024 then begin Result := inttostr(Size)+' Byte'; exit; end; if (1024 <= Size) and (Size < 1048576) then begin Result := floattostr((round((Size/1024)*100))/100)+' KB'; exit; end; if (1048576 <= Size) and (Size < 1099511627776) then begin Result := floattostr((round((Size/1048576)*100))/100)+' MB'; exit; end; if Size > 1099511627776 then begin Result := floattostr((round((Size/1099511627776)*100))/100)+' GB'; end; end; procedure THaupt.IdHTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode; const AWorkCountMax: Integer); begin FTime := GetTickCount; FBytes := 0; Application.ProcessMessages; end; procedure THaupt.IdHTTPWork(Sender: TObject; AWorkMode: TWorkMode; const AWorkCount: Integer); begin if not((GetTickCount - FTime) <= 0) then begin try SpeedLabel.caption := Format('%.2f KB/s', [(AWorkCount - FBytes) / (GetTickCount - FTime)]); except end; end; FTime := GetTickCount; FBytes := AWorkCount; Application.ProcessMessages; end; procedure THaupt.Download(AFile :String); var BytesKopiert, BytesInsgesamt : int64; lStream: TFileStream; begin //Initialiesieren Status.Caption := ''; BytesKopiert := 0; Progress.Position := 0; //In edit 1 steht die downzuladene Datei (z.b. [url]http://www.server.com/datei.dat[/url]) Status.Caption := 'Prüfe Header'; // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert IdHTTP.Head(URL+AFile); BytesInsgesamt := IdHTTP.Response.ContentLength; //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige) if BytesInsgesamt = -1 then begin Status.Caption := 'Normalles herunterladen'; Status.Caption := 'Erstelle Datei'; //In Edit 2 steht welche Datei (z.b. C:\datei.dat) //Datei erstellen lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone); try //und "normal" herunterladen idHTTP.Get(URL+AFile, lStream); finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; SpeedLabel.caption := 'Fertig'; exit; end; //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt. Progress.Max := BytesInsgesamt; Status.Caption := 'Erstelle Datei'; //In Edit 2 steht welche Datei (z.b. C:\datei.dat) //Datei erstellen lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone); lStream.Position := 0; try repeat // Damit sich das Programm nicht aufhängt Application.ProcessMessages; //Nun setzen wir den Start nach die bereits kopierten Bytes IdHTTP.Request.ContentRangeStart := BytesKopiert; //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then begin //Hier wird einmal die cFileSplitSize eingestellt IdHTTP.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1; end //Den rest der Datei else IdHTTP.Request.ContentRangeEnd := BytesInsgesamt; Application.ProcessMessages; //Den eingesttelten Teil herunterladen und ihn die Datei speichern IdHTTP.Get(URL+AFile, lStream); //Progress und Status aktualliesieren Progress.Position := BytesKopiert; Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt); //BytesKopiert weiter setzen BytesKopiert := BytesKopiert+cFileSplitSize; until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; SpeedLabel.caption := 'Fertig'; Progress.Position := 100; end; procedure THaupt.Button1Click(Sender: TObject); begin download('DateiNr1'); // Meine Dateien sind im Schnitt 500KB groß download('DateiNr2'); end; end. |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
also bei mir läufts. :cheers:
ich hab nur nen paar schönheitsfehler beseitigt... Wie das Tauschen der Zeilen
Delphi-Quellcode:
oder den Progressbar am ende auf max setzen.
//BytesKopiert weiter setzen
BytesKopiert := BytesKopiert+cFileSplitSize; //Progress und Status aktualliesieren Progress.Position := BytesKopiert; Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt);
Delphi-Quellcode:
ich habe allerdings festgestellt, das zu kleine Downloadblöcke die geschwindigkeit derbe hemmen. :cry:
Progress.Position := BytesInsgesamt;
leider ist das schon bei 100Kb bemerkbar, nur bei 1x DSL wird das leider schon verdammt träge mit der aktuallisierung. die geschwindigkeitsanziege hingegen ist dabei noch flink unterwegs :P hab vorher noch die was mit indy gemacht. cya |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
Hi das ist mein CodeLib eintrag :-D ... des nächste mal kannst du mir ruhig eine pn schicken :zwinker:
so ich glaub ich hab deinen fehler gefunden:
Delphi-Quellcode:
Des hast du zweimal drinnen ... wenn du die procedure aufrufst dann will er eine Datei auf den Pfad ".\DateiNr1" anlegen, korriger mich wenn ich mich täusche aber das kann nicht gehen. Du musst bei deiner Procedure noch einen zweiten Paramter ein bauen (z.b. "FilePath : String") und dann den Stream mit
lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone);
Delphi-Quellcode:
initialiesieren.
lStream:=TFileStream.Create(FilePath, fmCreate or fmShareDenyNone);
So müsste es gehen :thumb: |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
Hallo! Ich will hiermit (siehe Quelltext) eine 513kb Große exe-Datei runterladen! Bei 480kb beendet er den Download und zeigt fertig an! Die Datei die er bis dahin runtergeladen hat, ist 4 MB groß! :shock:
Delphi-Quellcode:
Wäre super wenn ihr mir helfen könnt!
procedure TForm1.Button1Click(Sender: TObject);
var BytesKopiert, BytesInsgesamt : int64; lStream: TFileStream; begin //Initialiesieren Status.Caption := ''; BytesKopiert := 0; Progressbar1.Position := 0; //In edit 1 steht die downzuladene Datei (z.b. [url]http://www.server.com/datei.dat[/url]) Status.Caption := 'Prüfe Header'; // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert IdHTTP1.Head('http://wwww....roject1.exe'); BytesInsgesamt := IdHTTP1.Response.ContentLength; //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige) if BytesInsgesamt = -1 then begin Status.Caption := 'Normalles herunterladen'; Status.Caption := 'Erstelle Datei'; //In Edit 2 steht welche Datei (z.b. C:\datei.dat) //Datei erstellen lStream:=TFileStream.Create('c:\Project1.exe', fmCreate or fmShareDenyNone); try //und "normal" herunterladen idHTTP1.Get('http://www...Project1.exe', lStream); finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; Speedlabel.caption := 'Fertig'; exit; end; //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt. Progressbar1.Max := BytesInsgesamt; Status.Caption := 'Erstelle Datei'; //In Edit 2 steht welche Datei (z.b. C:\datei.dat) //Datei erstellen lStream:=TFileStream.Create('c:\Project1.exe', fmCreate or fmShareDenyNone); lStream.Position := 0; try repeat // Damit sich das Programm nicht aufhängt Application.ProcessMessages; //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then begin //Hier wird einmal die cFileSplitSize eingestellt IdHttp1.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1; end else IdHttp1.Request.ContentRangeEnd := BytesInsgesamt; Application.ProcessMessages; //Den eingesttelten Teil herunterladen und ihn die Datei speichern IdHTTP1.Get('http://www...Project1.exe', lStream); //Progress und Status aktualliesieren Progressbar1.Position := BytesKopiert; Speedlabel.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt); //BytesKopiert weiter setzen BytesKopiert := BytesKopiert+cFileSplitSize; until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; Status.caption := 'Fertig'; Progressbar1.Position := 100; end; Danke! |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
schau dir des tutorial noch mal an
hab was ändern muss da die indys aus irgendeinen grund des nicht mehr auf diese weiße unterstützen wie du hast :wall: |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
Habe ich versucht. Aber ich bekomme hier
Delphi-Quellcode:
das er Range nicht kennt (unbekannter Bezeichner)!
IdHttp.Request.Range := Format('%d-%d', [BytesInsgesamt, (BytesKopiert+cFileSplitSize-1)]);
Wenn ich 'Request.ContentRangeEnd' mache, gehts erstmal von der Syntax. Aber mit dem nicht kompletten Download-Problem! Gruß! |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
Ich habe das programm zum laufen bekommen und das auch mit mehr als 2 Dateien.
Bei mir war das Problem, dass der Header anscheinend nicht neu geladen werden konnte weil der alte noch drine war. Beim neuladen ga es eine Fehlermeldung. Also habe ich
Delphi-Quellcode:
vor
idhttp.Request.Clear;
Delphi-Quellcode:
gepackt
idhttp.Head(meineurlplusdatei);
Für die Copy - Paste Programmierer Hier meine lösung
Delphi-Quellcode:
//Initialiesieren
Status.Caption := ''; BytesKopiert := 0; Progress.Position := 0; Status.Caption := 'Prüfe Header'; // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert idhttp.Request.Clear; IdHTTP.Head(meineurlplusdatei); BytesInsgesamt := IdHTTP.Response.ContentLength; //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige) if BytesInsgesamt = -1 then begin Status.Caption := 'Normalles herunterladen'; Status.Caption := 'Erstelle Datei'; //Datei erstellen lStream:=TFileStream.Create(Hauptprogrammpfadplusdatei, fmCreate or fmShareDenyNone); try //und "normal" herunterladen idHTTP.Get(meineurlplusdatei, lStream); finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; SpeedLabel.caption := 'Fertig'; exit; end; //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt. Progress.Max := BytesInsgesamt; Status.Caption := 'Erstelle Datei'; //Datei erstellen lStream:=TFileStream.Create(Hauptprogrammpfadplusdatei, fmCreate or fmShareDenyNone); lStream.Position := 0; try repeat // Damit sich das Programm nicht aufhängt Application.ProcessMessages; //Nun setzen wir den Start nach die bereits kopierten Bytes IdHTTP.Request.ContentRangeStart := BytesKopiert; //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then begin //Hier wird einmal die cFileSplitSize eingestellt IdHTTP.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1; end //Den rest der Datei else IdHTTP.Request.ContentRangeEnd := BytesInsgesamt; Application.ProcessMessages; //Den eingesttelten Teil herunterladen und ihn die Datei speichern IdHTTP.Get(meineurlplusdatei, lStream); //BytesKopiert weiter setzen BytesKopiert := BytesKopiert+cFileSplitSize; //Progress und Status aktualliesieren Progress.Position := BytesKopiert; Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt); until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig finally if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt end; //Alles auf fertig stellen Status.Caption := 'Fertig'; SpeedLabel.caption := 'Fertig'; Progress.Position := BytesInsgesamt; |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
warum macht ihr euch das leben schwer?
idHttp.Response.ContentStream.Position gibt an wie viel bytes aktuell gedownloaded sind. geändertes quellcode:
Delphi-Quellcode:
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, StdCtrls, ComCtrls; type TForm1 = class(TForm) Progress: TProgressBar; SpeedStatus: TLabel; Status: TLabel; Edit1: TEdit; Edit2: TEdit; IdHTTP: TIdHTTP; Button1: TButton; procedure IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer); procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private BytesInsgesamt: Integer; FTime: Longword; //Beide Variablen werden für die kb/sec anzeige gebraucht FBytes: Longword; // --"-- { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function GetSizeName(const Size : int64): String; begin Result := 'Fehler'; if Size = -1 then exit; if Size < 1024 then begin Result := inttostr(Size)+' Byte'; exit; end; if (1024 <= Size) and (Size < 1048576) then begin Result := floattostr((round((Size/1024)*100))/100)+' KB'; exit; end; if (1048576 <= Size) and (Size < 1099511627776) then begin Result := floattostr((round((Size/1048576)*100))/100)+' MB'; exit; end; if Size > 1099511627776 then begin Result := floattostr((round((Size/1099511627776)*100))/100)+' GB'; end; end; procedure TForm1.Button1Click(Sender: TObject); var lStream: TFileStream; begin Status.Caption := 'Prüfe Header'; Application.ProcessMessages; IdHTTP.Head(Edit1.Text); BytesInsgesamt := IdHTTP.Response.ContentLength; Status.Caption := GetSizeName(BytesInsgesamt); Progress.Max := BytesInsgesamt; Application.ProcessMessages; lStream:= TFileStream.Create(Edit2.Text, fmCreate); idHTTP.Get(edit1.Text, lStream); lStream.Free; progress.Position := progress.Max; end; procedure TForm1.FormCreate(Sender: TObject); begin edit2.Text := ExtractFilePath(ParamStr(0))+'Test.Dat'; end; procedure TForm1.IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer); begin if not((GetTickCount - FTime) <= 0) then begin try SpeedStatus.caption := Format('%.2f KB/s', [(AWorkCount - FBytes) / (GetTickCount - FTime)]); except end; end; FTime := GetTickCount; FBytes := AWorkCount; Progress.Position := idHttp.Response.ContentStream.Position; Application.ProcessMessages; end; end. |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
idHttp.Response.ContentStream.Position
Ist das Threadsafe? |
Re: Indy Http Download+Fortschritt als Funktion geht nicht
Hoi,
nur mal ne frage am rande: warum verwendet ihr nicht einfach aWorkcount und Aworkcountmax? ich denke das ist immernoch die einfachste variante oder? |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:50 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-2025 by Thomas Breitkreuz