Nun ich habe das Problem inzwischen dadurch "gelöst", indem ich statt dem verbuggeten Microsoft/Borland urlDownloadToFile bzw. TDownLoadURL Zeug mir eine neue Thread-Download Klasse auf Basis der Indys geschrieben haben, die mit HTTP get arbeitet. Also falls jemand mal ein ähnliches Problem hat, versucht es damit:
Delphi-Quellcode:
unit ThreadDownload;
interface
uses classes, IdHTTP;
type
TThreadDownload =
class (TThread)
protected
totalSize : cardinal;
fileURL :
string;
statusMessage :
string;
HTTP : TIdHTTP;
Content : TFilestream;
procedure Execute;
override;
public
isDownloading : boolean;
constructor create (
url,path :
string);
procedure cancel;
function getActualSize : cardinal;
function getTotalSize : cardinal;
function getStatusMessage :
string;
function getDownloadSuccess : boolean;
procedure FreeInstance;
override;
end;
implementation
constructor TThreadDownload.create (
url,path:
string);
//
// Object Initialization
//
begin
// signalize the download-thread is running
isDownloading := true;
fileURL :=
url;
Content := TFilestream.Create (path,fmcreate);
HTTP := TIdHTTP.Create;
inherited create (false);
end;
procedure TThreadDownload.Execute;
//
// Thread
//
begin
statusMessage := '
Verbinde';
// get filesize
HTTP.Head (fileURL);
totalSize := HTTP.Response.ContentLength;
statusMessage := '
Download gestartet';
HTTP.Get (fileURL,Content);
statusMessage := '
Download beendet';
// signalize the download-thread was stopped
isDownloading := false;
end;
procedure TThreadDownload.cancel;
//
// cancels the download
//
begin
HTTP.Disconnect;
statusMessage := '
Download abgebrochen';
// signalize the download-thread was stopped
isDownloading := false;
end;
function TThreadDownload.getActualSize : cardinal;
//
// returns the number of bytes already downloaded
//
begin
result := Content.Position;
end;
function TThreadDownload.getTotalSize : cardinal;
//
// returns the file's size in byte
//
begin
result := totalSize;
end;
function TThreadDownload.getStatusMessage :
string;
//
// returns the actual status-message
//
begin
result := statusMessage;
end;
function TThreadDownload.getDownloadSuccess : boolean;
//
// is true if the file was completely downloaded
//
begin
if (Content.Position = totalSize)
then result := true
else result := false;
end;
procedure TThreadDownload.FreeInstance;
//
// Garbage Collection
//
begin
Content.Free;
HTTP.Free;
inherited FreeInstance;
end;
end.
Ein Implementations-Beispiel wäre:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
//
// downlad [url]http://upload.wikimedia.org/wikipedia/en/d/d4/Delphi_Composite.jpg[/url]
//
var url,path :
string;
begin
url := '
http://upload.wikimedia.org/wikipedia/en/d/d4/Delphi_Composite.jpg';
path := '
c:\Delphi.jpg';
DownloadThread := TThreadDownload.create (
url,path);
DownloadThread.FreeOnTerminate := false;
while (DownloadThread.isDownloading)
do
begin
sleep (100);
Application.ProcessMessages;
end;
showmessage ('
Done!');
DownloadThread.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
//
// cancel download
//
begin
DownloadThread.cancel;
end;
Das cancel hier macht keine Zicken und der Thread lässt sich danach auch anstandslos beenden und die Dateileiche wird freigegeben. Mithilfe von getActualSize und getTotalSize kann man sich die aktuelle Geschwindigkeit berechnen und so im Falle eines Verbindungsabbruchs,
IP-Wechsels, ect. wenn die Geschwindigkeit eine gewisse Zeig lang bei 0 lag, den Download dann automatisch abbrechen und wiederholen.