|
![]() |
Registriert seit: 7. Mai 2008
... leider nur ein Aufsatz für die Indy Komponente.
Es ist meine erste Klasse in Delphi. Ich bitte dass ihr wenn ihr Lust habt mal drüber schaut und vllt ein paar Verbesserungs Tipps geben könntet ![]() Und daher bitte ich gerade auf Styleguide zu achten. Ich an den meisten Stellen(bis auf 2) auch die 80 Zeichen marke eingehalten. An 2 Stellen muss ich noch eine gute Formatierung suchen... ![]()
Delphi-Quellcode:
unit HTTPDownloader;
interface uses SysUtils, StrUtils, Dialogs, Classes, Forms, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdAuthentication, IdHTTP; type TUpdateRate = (urFast, urNormal, urSlow); TDownload = record ID : integer; Count : integer; URL : array[0..3] of string; Size : int64; SizeFormated : string; Downloaded : int64; DownloadedFormated : string; DownloadedPercent : integer; end; TDownloadWork = procedure(Download : TDownload) of object; TDownloadBegin = procedure(Download : TDownload) of object; TDownloadEnd = procedure(Download : TDownload) of object; THTTPDownloader = class private // Variablen bolAppProcessMsg: boolean; intDownloads : integer; urUpdateRate : TUpdateRate; arrDownloadList : array of array[0..1] of string; objHTTP : TidHTTP; CurrentDownload : TDownload; // Ereignisse DownloadWork : TDownloadWork; DownloadBegin : TDownloadBegin; DownloadEnd : TDownloadEnd; // Funktionen procedure DownloadOnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); procedure ClearCurrentDownload; function GetSizeName(const Size : int64): String; public // Constructor / Destructor constructor Create; destructor Destroy; override; // Funktionen / Prozeduren function GetURLFileSize(aURL : string) : int64; function Download(aURL : string; aDest : string) : boolean; procedure ItemsDownload; procedure ItemsAdd(aURL : string; aDest : string); procedure ItemsClear; // Eigenschaften property UpdateRate : TUpdateRate read urUpdateRate write urUpdateRate; property ProcessMessages : boolean read bolAppProcessMsg write bolAppProcessMsg; property Downloads : integer read intDownloads; property PercentCurrent : integer read intDownloads; property PercentAll : integer read intDownloads; // Ereignisse property OnDownloadWork : TDownloadWork read DownloadWork write DownloadWork; property OnDownloadBegin: TDownloadBegin read DownloadBegin write DownloadBegin; property OnDownloadEnd : TDownloadEnd read DownloadEnd write DownloadEnd; end; var Downloader : THTTPDownloader; implementation // ============================================================================= // Public // ============================================================================= constructor THTTPDownloader.Create; begin inherited; // HTTP Objekt (Indy) erzeugen und Eigenschaften setzen objHTTP := TidHTTP.Create(nil); objHTTP.AllowCookies := true; objHTTP.RedirectMaximum := 10; // HTTP Objekt Ereigniss zuweißen objHTTP.OnWork := DownloadOnWork; // Variablen Initialisieren intDownloads := 0; SetLength(arrDownloadList,0); end; destructor THTTPDownloader.Destroy; begin inherited; // Aufräumen objHTTP.Destroy; end; procedure THTTPDownloader.ItemsAdd(aURL : string; aDest : string); begin // DownloadList-Array um eins erhöhen SetLength(arrDownloadList,Length(arrDownloadList)+1); // 2te Dimension des Arrays befüllen arrDownloadList[Length(arrDownloadList)-1,0] := aURL; arrDownloadList[Length(arrDownloadList)-1,1] := aDest; // Download Property Var. um 1 erhöhen und Record zuweisen inc(intDownloads); CurrentDownload.Count := intDownloads; end; procedure THTTPDownloader.ItemsClear; begin // DownloadList-Array auf 0 Setzen SetLength(arrDownloadList, 0); // Download Property Var. auf 0 setzen und Record zuweißen intDownloads := 0; CurrentDownload.Count := 0; end; procedure THTTPDownloader.ItemsDownload; var i: Integer; begin // Jedes Element des DownloadList-Arrays durchlaufen und Datei herunterladen for i := 0 to Length(arrDownloadList) - 1 do begin CurrentDownload.ID := i + 1; Self.Download(arrDownloadList[i,0],arrDownloadList[i,1]); end; end; function THTTPDownloader.Download(aURL : string; aDest : string) : boolean; var DownloadStream : TMemoryStream; begin // Standartrückgabewert setzen (wird bei Fehlerfall geändert) result := true; // Stream erzeugen DownloadStream := TMemoryStream.Create; DownloadStream.Clear; // Versuche Datei herunterzulasen und abzuspeichern try // Header Informationen abfragen objHTTP.Head(aURL); // ProcessMessages falls Property gesetzt if bolAppProcessMsg then Application.ProcessMessages; // RECORD befüllen CurrentDownload.Size := objHTTP.Response.ContentLength; CurrentDownload.SizeFormated := Self.GetSizeName(objHTTP.Response.ContentLength); CurrentDownload.URL[0] := aURL; CurrentDownload.URL[1] := copy( copy(aURL, 8, length(aURL)), 0, Pos('/', copy( aURL, 8 , length(aURL) ) )-1 ); CurrentDownload.URL[2] := copy( aURL, length(aURL) - ( Pos( '/', AnsiReverseString(aURL) )-1 ) + 1, length(aURL) ); // Ereigniss : DownloadBegin aufrufen - falls definiert if @DownloadBegin <> nil then DownloadBegin(CurrentDownload); // ProcessMessages falls Property gesetzt if bolAppProcessMsg then Application.ProcessMessages; // Download in Stream laden objHTTP.Get(aURL, DownloadStream); // Ereigniss : DownloadEnd aufrufen - falls definiert if @DownloadEnd <> nil then DownloadEnd(CurrentDownload); // ProcessMessages falls Property gesetzt if bolAppProcessMsg then Application.ProcessMessages; // Stream als Datei speichern DownloadStream.SaveToFile(aDest); except // Rückgabewert setzen - Fehler ist aufgetreten result := false; end; // Aufräumen DownloadStream.Free; //Self.ClearCurrentDownload; end; function THTTPDownloader.GetURLFileSize(aURL : string) : int64; begin // Versuche Header Informationen abzufragen try // Ermittle HeadderInformationen objHTTP.Head(aURL); // ProcessMessages falls Property gesetzt if bolAppProcessMsg then Application.ProcessMessages; // Lese HeaderInformationen in Rückgabewert result := objHTTP.Response.ContentLength; except // Falls ein Fehler auftritt, ist der Rückgabewert -1 result := -1; end; end; // ============================================================================= // Private // ============================================================================= procedure THTTPDownloader.ClearCurrentDownload; begin // Record auf Standartwerte zurücksetzen CurrentDownload.Size := 0; CurrentDownload.SizeFormated := ''; CurrentDownload.ID := 0; CurrentDownload.Count := 0; CurrentDownload.Downloaded := 0; CurrentDownload.DownloadedFormated := ''; CurrentDownload.DownloadedPercent := 0; CurrentDownload.URL[0] := ''; CurrentDownload.URL[1] := ''; CurrentDownload.URL[2] := ''; end; procedure THTTPDownloader.DownloadOnWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64); var intRate : integer; begin // Standartwer falls Property nicht gesetzt = 2, urNormal intRate := 2; // urUpdateRate auswählen case urUpdateRate of urFast : begin intRate := 1; end; urNormal : begin intRate := 2; end; urSlow : begin intRate := 3; end; end; // Funktion verlassen falls Rate nicht zutrifft und AWorkCount == CurrentDownload.Size if (not(AWorkCount = CurrentDownload.Size)) and ((AWorkCount mod intRate) <> 0) then exit; // Ereigniss : DownloadWork aufrufen - falls definiert if @DownloadWork <> nil then begin // Record.Downloaded setzen CurrentDownload.Downloaded := AWorkCount; CurrentDownload.DownloadedPercent := round((AWorkCount / CurrentDownload.Size) * 100); CurrentDownload.DownloadedFormated := Self.GetSizeName(AWorkCount); // Ereigniss DownloadWork DownloadWork(CurrentDownload); // ProcessMessages falls Property gesetzt if bolAppProcessMsg then Application.ProcessMessages; end; end; function THTTPDownloader.GetSizeName(const Size : int64): String; begin Result := 'Error'; 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; end. Gruß, Real-TTX
You think my answer is stupid ? Read This:
EN - ![]() DE - ![]() |
|
#2
Besser wäre es, den Code entweder hier in [ delphi ][ /delphi ] - Tags einzufügen, oder in eine Unit zu packen und in Anhang verfrachten.
![]()
米斯蘭迪爾
|
![]() |
|
#3
Ich hab jetzt nur mal kurz über die Formatierung geguckt ... und etwas ist mir ins Auge gestochen:
Sowas finde ich sehr unleserlich ...
Delphi-Quellcode:
Jeder Parameter auf einer neuen Zeileund einmal sogar das Komma extra
CurrentDownload.URL[1] := copy(
copy(aURL, 8, length(aURL)), 0, Pos('/', copy( aURL, 8 , length(aURL) ) )-1 ); CurrentDownload.URL[2] := copy( aURL, length(aURL) - ( Pos( '/', AnsiReverseString(aURL) )-1 ) + 1, length(aURL) ); ![]() Soooo schlimm isses imho auch nicht, wenn man mal über 80 Zeichen kommt ![]() |
![]() |
Delphi 12 Athens |
#4
Delphi-Quellcode:
dieses ist immer <> nil, denn die Variablen sind immer vorhanden
if @DownloadBegin <> nil then
DownloadBegin(CurrentDownload); if @DownloadEnd <> nil then DownloadEnd(CurrentDownload); if @DownloadWork <> nil then begin
Delphi-Quellcode:
if Assigned(DownloadBegin) then
DownloadBegin(CurrentDownload); if Assigned(DownloadEnd) then DownloadEnd(CurrentDownload); if Assigned(DownloadWork) then begin // und wenn schon NIL, dann eher so if Pointer(DownloadBegin) <> nil then DownloadBegin(CurrentDownload);
Delphi-Quellcode:
schonmal etwas vom ELSE gehört und wozu die Begin-End?
// Standartwer falls Property nicht gesetzt = 2, urNormal
intRate := 2; // urUpdateRate auswählen case urUpdateRate of urFast : begin intRate := 1; end; urNormal : begin intRate := 2; end; urSlow : begin intRate := 3; end; end;
Delphi-Quellcode:
// urUpdateRate auswählen
case urUpdateRate of urFast : intRate := 1; urSlow : intRate := 3; else intRate := 2; end; mit ein paar ELSE könne man einige Vergleiche eh weglassen, samt der "unnötigen" Exit. ja meinst du, daß über 1 Terrabyte wirklich nötig sind? PS: laut berechnung ist dein GB ein TB und GBhast du ganz vergessen ![]() (1.099.511.627.776 = 1 TB)
Delphi-Quellcode:
.......
function THTTPDownloader.GetSizeName(const Size : int64): String;
begin if Size > 1073741824 then Result := floattostr(trunc(Size/1073741824*100)/100)+' GB' else if Size > 1048576 then Result := floattostr(trunc(Size/1048576*100)/100)+' MB' else if Size > 1024 then Result := floattostr(trunc(Size/1024*100)/100)+' KB' else if Size >= 0 then Result := inttostr(Size)+' Byte' else Result := 'Error'; end; PS: von da drüben läßt sich dein Code nicht nutzen ... beim Rauskopieren wird da je Zeile eine Zeile mit 'nem # eingefügt ... voll unpraktisch |
![]() |
|
#5
![]() PS: von da drüben läßt sich dein Code nicht nutzen ... beim Rauskopieren wird da je Zeile eine Zeile mit 'nem # eingefügt ... voll unpraktisch
![]() ![]() ![]()
米斯蘭迪爾
|
![]() |
Delphi 12 Athens |
#6
![]() ![]()
Delphi-Quellcode:
wo die Definition doch gleich ist, mach doch einfach eine Definition raus.
TDownloadWork = procedure(Download : TDownload) of object;
TDownloadBegin = procedure(Download : TDownload) of object; TDownloadEnd = procedure(Download : TDownload) of object; TDownloadCallback = procedure(const Download : TDownload) of object; oder eventuell gleich nur eine CallbackProzedur für alles
Delphi-Quellcode:
im Allgemeinem machen sich Const bei einigen anderen Prozeduren auch nicht schlecht (z.B. bei Int64- und String-Parametern)
TDownloadState = (dsBegin, dsWork, dsEnd);
TDownloadCallback = procedure(const Download : TDownload; State: TDownloadState) of object;
Delphi-Quellcode:
function GetURLFileSize(const aURL : string) : int64;
function Download(const aURL, aDest : string) : boolean; procedure ItemsAdd(const aURL, aDest : string); |
![]() |
|
#7
![]() im Allgemeinem machen sich Const bei einigen anderen Prozeduren auch nicht schlecht (z.B. bei Int64- und String-Parametern)
Warum?
米斯蘭迪爾
|
![]() |
Delphi 12 Athens |
#8
wenn die Variablen eh nicht verändert werden sollen, wozu sie veränderbar machen?
(also Prozedurintern) gut, bei Strings gibt es die Referenzzählung, aber nicht immer (vorallem nicht bei WideString) und bei Records und auch allem über 32 Bit wird ohne das Const erst eine Kopie des Parameters angelegt, worin die Prozeduinternen änderungen stattfinden können. übergib mal z.B. ein rießiges Static-Array, einen großen Record oder einen langen WideString ... diese müssen erst kopiert und am Ende wieder freigegeben werden. und auch bei kleinen Strukturen müßte das erst von Delphi gemacht werden, selbst wenn es unnötig wäre. CONST (könnte man auch als IN), VAR, OUT und (nichts) gibt es ja nicht umsonst zur Auswahl und Const bzw. Var wird bei "größeren" Strukturen dann einfach als Zeiger auf die Originaldaten umgesetzt und läuft nicht über 'ne "Kopie". (kleine Ausnahmen bilden Objekte, welche "nur" Zeiger sind, sowie Strings bzw. DynArrays, welche eine Referenzzählung besitzen) |
![]() |
Delphi 2007 Enterprise |
#10
Soviel, kann ich jetzt auf die schnelle nicht verarbeiten :O
Aber danke für die Tipps. Das mit den Konstanten bei Funktinen ist wirklich sehr hübsch. ![]()
Delphi-Quellcode:
oder eventuell gleich nur eine CallbackProzedur für alles
TDownloadWork = procedure(Download : TDownload) of object;
TDownloadBegin = procedure(Download : TDownload) of object; TDownloadEnd = procedure(Download : TDownload) of object;
Delphi-Quellcode:
wo die Definition doch gleich ist, mach doch einfach eine Definition raus.
TDownloadState = (dsBegin, dsWork, dsEnd);
TDownloadCallback = procedure(const Download : TDownload; State: TDownloadState) of object; TDownloadCallback = procedure(const Download : TDownload) of object; ![]() PS: Die Funktion GetSizeName habe ich selbst nur hier aus dem Forum gestohlen ![]() bei der Mehrfachverzweigung habe ich Begin End genommen weil es ohne nicht ging? Und muss man da nicht normalerweise auch break benutzen, da es nur dumme DOS Sprungmarken sind ? |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |