Downloading a file from the Internet, if possible cancel the download at any time

I want to upload a file from my Delphi program into a separate download thread.

The problem is that the main program can be closed at any time (thus, the download stream can also be interrupted at any time). Therefore, even if there is no connection or the server is lagging behind in precious seconds, I need a way to complete the download stream in a second or two.

What function do you recommend to use?

I experimented with InterOpenURL / InternetReadFile, but it does not have a timeout parameter. It has an asynchronous version, but I cannot find any working Delphi examples, and I'm not sure that the asynchronous version will protect me from freezes ...

Using sockets has been recommended to me before, but TClientSocket also does not have a timeout function.

I need to be fully prepared, so if a user has problems connecting to the Internet on his / her computer or the web server remains behind, my application does not freeze before closing.

Please note that I do not want to use either third-party components or Indy. Any sample code is much appreciated.

Thanks!

+7
multithreading delphi download delphi-7 wininet
source share
4 answers

TWinSocketStream has a timeout. You basically create a blocking socket and then create a TWinSocketStream using this read / write socket. (sort of using StreamWriter). Then you loop until the connection is closed, the thread stops, or you reach the number of bytes expected. There WaitForData (), which allows you to check incoming data with a timeout, so you never "lock" during this timeout.

You, however, will have to handle the http process yourself. those. send "GET" and then read the response header to determine how many bytes to expect, but it's not too difficult.

+2
source share

It works.

 var DownloadAbort: boolean; procedure Download(const URL, FileName: string); var hInet: HINTERNET; hURL: HINTERNET; Buffer: array[0..1023] of AnsiChar; BufferLen, amt: cardinal; f: file; const UserAgent = 'Delphi Application'; // Change to whatever you wish begin DownloadAbort := false; hInet := InternetOpen(PChar(UserAgent), INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); try hURL := InternetOpenUrl(hInet, PChar(URL), nil, 0, 0, 0); try FileMode := fmOpenWrite; AssignFile(f, FileName); try Rewrite(f, 1); repeat InternetReadFile(hURL, @Buffer, SizeOf(Buffer), BufferLen); BlockWrite(f, Buffer[0], BufferLen, amt); if DownloadAbort then Exit; until BufferLen = 0; finally CloseFile(f); end; finally InternetCloseHandle(hURL); end; finally InternetCloseHandle(hInet); end; end; 

In practice, the above code will be part of your Execute stream, and you do not need DownloadAbort ; intead, you check

 if Terminated then Exit; 
+5
source share

Thanks GrandmasterB, here is the code that I managed to compile: (it in my thread Executes a block)

 var Buffer: array [0..1024 - 1] of Char; SocketStream: TWinSocketStream; RequestString: String; BytesRead: Integer; begin try ClientSocket.Active := true; DownloadedData := ''; FillChar(Buffer, SizeOf(Buffer), #0); if not Terminated then begin // Wait 10 seconds SocketStream := TWinSocketStream.Create(ClientSocket.Socket, 10000); try // Send the request to the webserver RequestString := 'GET /remotedir/remotefile.html HTTP/1.0'#13#10 + 'Host: www.someexamplehost.com'#13#10#13#10; SocketStream.Write(RequestString[1], Length(RequestString)); // We keep waiting for the data for 5 seconds if (not Terminated) and SocketStream.WaitForData(5000) then repeat // We store the data in our buffer BytesRead := SocketStream.Read(Buffer, SizeOf(Buffer)); if BytesRead = 0 then break else DownloadedData := DownloadedData + Buffer; until Terminated or (not SocketStream.WaitForData(2000)); finally // Close the connection SocketStream.Free; if ClientSocket.Active then ClientSocket.Active := false; end; end; except end; 

You should put this in the stream constructor:

  ClientSocket := TClientSocket.Create(nil); ClientSocket.Host := 'www.someexamplehost.com'; ClientSocket.Port := 80; ClientSocket.ClientType := ctBlocking; inherited Create(false); // CreateSuspended := false; 

And this is for the descriptor:

  ClientSocket.Free; inherited; 
+2
source share

From delphi.about.com

 uses ExtActns, ... type TfrMain = class(TForm) ... private procedure URL_OnDownloadProgress (Sender: TDownLoadURL; Progress, ProgressMax: Cardinal; StatusCode: TURLDownloadStatus; StatusText: String; var Cancel: Boolean) ; ... implementation ... procedure TfrMain.URL_OnDownloadProgress; begin ProgressBar1.Max:= ProgressMax; ProgressBar1.Position:= Progress; end; function DoDownload; begin with TDownloadURL.Create(self) do try URL:='http://0.tqn.com/6/g/delphi/b/index.xml'; FileName := 'c:\ADPHealines.xml'; OnDownloadProgress := URL_OnDownloadProgress; ExecuteTarget(nil) ; finally Free; end; end; 

{Note: URL property points to Internet FileName - this is a local file}

+1
source share

All Articles