Einzelnen Beitrag anzeigen

Hedge

Registriert seit: 30. Jun 2007
278 Beiträge
 
Delphi 2009 Professional
 
#1

Probleme mit 'IdHTTP + Fortschrittsanzeige' aus CodeLibrary

  Alt 19. Nov 2009, 19:14
Ich war so frech aus folgendem CodeLibrary-Eintrag die Routine zu übernehmen um bei einem Dateidownload die Geschwindigkeit anzuzeigen: http://www.delphipraxis.net/internal...ct.php?t=56872

Leider treten dabei 2 verschiedene Probleme auf.
Ich teste jedes Mal mit einer 4MB großen zip-Datei

Wenn ich es auf dem lokalen Server teste, dann steht kurz nach dem Start des Download 'fertig' da, dabei wurden nur 120kb runtergeladen

Beim Test auf dem Remote-Server kriege ich an unterschiedlichen Zeitpunkten eine 'Connection Closed Gracefully'-Exception.

Ich benutze Delphi 2009 mit Indy 10.


Hier ist der Code meiner Unit:

Delphi-Quellcode:
unit AutoUpdateUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
  IdHTTP, StdCtrls;

type
  TAutoUpdateForm = class(TForm)
    AutoUpdateProgress: TProgressBar;
    HTTPAutoUpdate: TIdHTTP;
    SpeedStatus: TLabel;
    AutoUpdateStatus: TLabel;
    procedure HTTPAutoUpdateWorkBegin(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCountMax: Int64);
    procedure HTTPAutoUpdateWork(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Int64);
    procedure DoAutoUpdate(fileName:String);
  private
    { Private-Deklarationen }
    FTime: Longword; //Beide Variablen werden für die kb/sec anzeige gebraucht
    FBytes: Longword; // --"--
  public
    { Public-Deklarationen }
  end;

var
  AutoUpdateForm: TAutoUpdateForm;


const
  cFileSplitSize : Int64 = 40*1024; //40 KB größe stücke wird die Datei zerhackt

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 TAutoUpdateForm.DoAutoUpdate(fileName:String);
var
  BytesKopiert, BytesInsgesamt : int64;
  lStream: TFileStream;
  RemotePath: String;
begin
  RemotePath:='http://localhost/';
  self.Show;
  self.BringToFront;
  //Initialiesieren
  AutoUpdateStatus.Caption := '';
  BytesKopiert := 0;
  AutoUpdateProgress.Position := 0;
  //In edit 1 steht die downzuladene Datei (z.b. [url]http://www.server.com/datei.dat[/url])
  AutoUpdateStatus.Caption := 'Prüfe Header';
  // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert
  HTTPAutoUpdate.Head(RemotePath+fileName);
  BytesInsgesamt := HTTPAutoUpdate.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
    AutoUpdateStatus.Caption := 'Normalles herunterladen';
    AutoUpdateStatus.Caption := 'Erstelle Datei';
    //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
    //Datei erstellen
    lStream:=TFileStream.Create(ExtractFilePath(Application.ExeName)+fileName, fmCreate or fmShareDenyNone);
    try
      //und "normal" herunterladen
      HTTPAutoUpdate.Get(RemotePath+fileName, lStream);
    finally
      if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
    end;
    //Alles auf fertig stellen
    AutoUpdateStatus.Caption := 'Fertig';
    SpeedStatus.caption := 'Fertig';
    exit;
  end;
  //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt.
  AutoUpdateProgress.Max := BytesInsgesamt;
  AutoUpdateStatus.Caption := 'Erstelle Datei';
  //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
  //Datei erstellen
  lStream:=TFileStream.Create(ExtractFilePath(Application.ExeName)+fileName, 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
        HTTPAutoUpdate.Request.Range := Format('%d-%d', [BytesKopiert, (BytesKopiert+cFileSplitSize-1)]);
      end
      else HTTPAutoUpdate.Request.Range := Format('%d-', [BytesKopiert]);

      Application.ProcessMessages;
      //Den eingesttelten Teil herunterladen und ihn die Datei speichern
      HTTPAutoUpdate.Get(RemotePath+fileName, lStream);
      //Progress und Status aktualliesieren
      AutoUpdateProgress.Position := BytesKopiert;
      AutoUpdateStatus.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
    HTTPAutoUpdate.Request.Range := ''; //Verhindert das die nächste Anfrage in einem 206 Fehler endet
  end;
  //Alles auf fertig stellen
  AutoUpdateStatus.Caption := 'Fertig';
  SpeedStatus.caption := 'Fertig';
  AutoUpdateProgress.Position := 100;
end;

procedure TAutoUpdateForm.HTTPAutoUpdateWork(ASender: TObject;
  AWorkMode: TWorkMode; AWorkCount: Int64);
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;
  Application.ProcessMessages;
end;

procedure TAutoUpdateForm.HTTPAutoUpdateWorkBegin(ASender: TObject;
  AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
  FTime := GetTickCount;
  FBytes := 0;
  Application.ProcessMessages;
end;

end.
٩๏̯͡๏)۶
  Mit Zitat antworten Zitat