Forum > Networking and Web Programming

Indy 10: TCP/HTTPS downloads management OnWork

(1/2) > >>

torbente:
Hi:
Found a lot of articles related with this using HHTP, but bot a single one using TCP...


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var   ClientChannel : TIdTCPClient; function GetFile(filename:string):boolean;var  AFileStream : TFileStream;Beginresult := false;ClientChannel.Host:=PredefinedHost;ClientChannel.Port:=PredefinedPort;ClientChannel.ConnectTimeout:= 1000;ClientChannel.ReadTimeout:=500;//ClientChannel.OnWork:= ??; Whats going here?TRYClientChannel.Connect;ClientChannel.IOHandler.WriteLn('GETFILE:'+filename);AFileStream := TFileStream.Create(filename, fmCreate);   TRY   ClientChannel.IOHandler.ReadStream(AFileStream);   result := true;   EXCEPT on E:Exception do      begin      // Report error downloading the file      end;   END{Try};FINALLYAFileStream.Free;ClientChannel.Disconnect();END{try};End;  
This has worked for me for years, but now i need be able to "follow" the progress of the download (maybe a percentage of the completed download?) to be able to abort it (and also in case the user closes the app during a long download)

Thanks in advance.

Remy Lebeau:

--- Quote from: torbente on December 18, 2021, 02:56:29 am ---Found a lot of articles related with this using HHTP, but bot a single one using TCP...

--- End quote ---

The OnWork events work exactly the same way in all of Indy's components.


--- Quote from: torbente on December 18, 2021, 02:56:29 am ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---//ClientChannel.OnWork:= ??; Whats going here?
--- End quote ---

An event handler, obviously, for example:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TSomeClass.OnWorkHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);begin  ...end; var InstanceOfSomeClass: TSomeClass;...ClientChannel.OnWork := InstanceOfSomeClass.OnWorkHandler;
Alternatively, if you don't have an object instance to put the handler into, you can use a standalone procedure, but you will have to tweak the  function signature and then use the System.TMethod record to assign it to the event, eg:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// note the extra ASelf parameter!...procedure OnWorkHandler(ASelf: Pointer; ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);begin  ...end; var  M: TMethod;begin  M.Data := nil; // Or whatever you want the ASelf parameter to point at...  M.Code := @OnWorkHandler;  ClientChannel.OnWork := TWorkEvent(M);end;
Or:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  Evt: TWorkEvent;begin  TMethod(Evt).Data := nil; // Or whatever you want the ASelf parameter to point at...  TMethod(Evt).Code := @OnWorkHandler;  ClientChannel.OnWork := Evt;end;
Note, you will also need a handler for the OnWorkBegin event, too.  The OnWork event only tells you how many bytes have been transferred so far, but the OnWorkBegin event tells you how many bytes are expected, if known up front:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TSomeClass.OnWorkBeginHandler(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);begin  ...end; var InstanceOfSomeClass: TSomeClass;...ClientChannel.OnWorkBegin := InstanceOfSomeClass.OnWorkBeginHandler;
Or:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// note the extra ASelf parameter!...procedure OnWorkBeginHandler(ASelf: Pointer; ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);begin  ...end; var  M: TMethod;begin  M.Data := nil; // Or whatever you want the ASelf parameter to point at...  M.Code := @OnWorkBeginHandler;  ClientChannel.OnWorkBegin := TWorkBeginEvent(M);end;
Or:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---var  Evt: TWorkBeginEvent;begin  TMethod(Evt).Data := nil; // Or whatever you want the ASelf parameter to point at...  TMethod(Evt).Code := @OnWorkBeginHandler;  ClientChannel.OnWorkBegin := Evt;end;

--- Quote from: torbente on December 18, 2021, 02:56:29 am ---
--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---ClientChannel.IOHandler.ReadStream(AFileStream);
--- End quote ---

The default parameters of ReadStream() are AByteCount=-1 and AReadUntilDisconnect=False.  Under that specific combination, ReadStream() will first attempt to read an integer from the connection, indicating the stream's total byte size, before then reading that many bytes for the actual stream data.  That byte count will be passed to the OnWorkBegin event, and is expected to be transmitted as either a 4-byte Integer or an 8-byte Int64 depending on the IOHandler's LargeStream property.


--- Quote from: torbente on December 18, 2021, 02:56:29 am ---This has worked for me for years, but now i need be able to "follow" the progress of the download (maybe a percentage of the completed download?) to be able to abort it (and also in case the user closes the app during a long download)

--- End quote ---

Being able to calculate a percentage requires knowing how many bytes are actually in the file to begin with.  Is your server sending that byte count up front?

torbente:
I was able to find the way, using a design-time client and assigning the onworkbegin and onwork elements.

Since it was a download from a peer using a TCP connection, it do not have problems.

Now (i believe i could continue here since the post title perfectly fits) i want download (with onwork following) a file from github (so users can get last releases from there directly)


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---IdHTTPUpdate: TIdHTTP;  Function GetLastVerZipFile(filename:string):boolean;var  MS: TMemoryStream;BeginMS := TMemoryStream.Create;TRY   TRY   Form1.IdHTTPUpdate.HandleRedirects:=true;   Form1.IdHTTPUpdate.get('https://github.com/owner/repository/releases/download/version/xxx.zip', MS);    MS.SaveToFile(UpdatesDirectory+'filename.zip');   EXCEPT ON E:Exception do      begin      ShowMessage('Error downloading last release: '+E.Message);      end;   END{Try};FINALLYMS.Free;END{try};End;  
Im receiving invalid SSL protocol error. I placed the SSL files sin the same folder than the app but it neither worked. Any idea?

Remy Lebeau:

--- Quote from: torbente on January 11, 2022, 03:51:58 am ---Im receiving invalid SSL protocol error.

--- End quote ---

What is the EXACT error message, verbatim?  And how did you (or, did you, at all?) configure the SSLIOHandler assigned to the TIdHTTP.IOHandler property?


--- Quote from: torbente on January 11, 2022, 03:51:58 am ---I placed the SSL files sin the same folder than the app but it neither worked.

--- End quote ---

Are you referring to the two OpenSSL DLLs?  Which version of the DLLs are you using?

torbente:
 :D Sorry, forgot to mention it...


--- Quote ---What is the EXACT error message, verbatim?

--- End quote ---

Error downloading last release: Error connecting with SSL.
error:1409442E:SSL routines:ssl3_read_bytes:tlsv1 alert protocol version


--- Quote ---And how did you (or, did you, at all?) configure the SSLIOHandler assigned to the TIdHTTP.IOHandler property?
--- End quote ---

Well, im implemented this...


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---IdSSLIOHandler:= TIdSSLIOHandlerSocketOpenSSL.Create;...Form1.IdHTTPUpdate.IOHandler:=IdSSLIOHandler;
And i was receiving this error:

Error downloading last release: Socket Error # 10060
Connection timed out.


--- Quote ---Are you referring to the two OpenSSL DLLs?  Which version of the DLLs are you using?
--- End quote ---

Yes, ssleay32.dll and libeay32.dll, version 1.0.2

Navigation

[0] Message Index

[#] Next page

Go to full version