Brian Warner 0 Posted December 2, 2022 I'm looking for a kick start in the right direction. Is it possible to have multiple connections such that I can have more than one file download going at a time (a cheap version of FileZilla). Many of the software users will find FileZilla too large a leap for their skills. I presume each one requires its own TidFTP and SSLIOHandler pair. I've playing with putting the set in a TParallel.For loop but get a general "too many exceptions" in the debugger after a few seconds. Running outside the IDE doesn't give anything more specific about what's wrong. Generally, Use connection 1 to get file listing. Iterate through the directory listing to create an array of 0..4 of <IdFTP, FileName>. Go through that list such that up to five GET statements are running. I've disconnected the events so that there is no updating of controls, i.e., no need to call Synchronize. Thanks for any help. Brian Share this post Link to post
programmerdelphi2k 237 Posted December 2, 2022 (edited) each FTP session, needs: user, password, a file to upload; then, you need use a way to send this data, like using a "thread", or in your case "n" threads. Each one for a FTP send! then, each thread will be independent and autonomous each others! needs controls like all works, mainly when any exception occurs! Edited December 2, 2022 by programmerdelphi2k Share this post Link to post
Fr0sT.Brutal 900 Posted December 2, 2022 From the nature of FTP transfers I'm afraid there couldn't be 1 ctrl connection + several data ones. So you'd have to create several fully independent FTP clients Share this post Link to post
Brian Warner 0 Posted December 2, 2022 Thanks for the replies. I think I'm on the right track. I thought about creating "simple" threads, each with its own TidFTP/SSLHandler pair but thought the TParallel.For loop might speed things along. Here's what I have so far. I'm hoping that "fully independent FTP clients" doesn't mean actually have separate forms, just one TidFPT/SSLHander component pair per "client", both setup with the necessary information to do an autologin to the correct server. IOW, independently, each does what's intended. type TDL = packed record FTP : TIdFTP; LI : TidFTPListItem; end; var DL := array[0..4] of TDL; { Each Cnx is a TidFTP component on the form that has its own SSL handler component } Cnx[0] := idFTPDL; Cnx[1] := idFTP1; Cnx[2] := idFTP2; Cnx[3] := idFTP3; Cnx[4] := idFTP4; Cnx[0].OnWork := nil; // disables code that updates a TPanel. for I := 0 to 4 do begin if (not Cnx[I].Connected) then begin Cnx[I].Connect; end; Cnx[I].OnWork := nil; end; try for I := 0 to 4 do begin Cnx[I].ChangeDir(ARemoteDir); end; var Idx : integer := 0; var Q : integer := 0; SetLength(DL, Idx); { Didn't use SetLength(DL, DirCount) since it contains one or more ditDirectory items. This leads to some issues below when distributing the file list to the five FTP components. } Cnx[0].List; var DirCount := Cnx[0].DirectoryListing.Count; for I := 0 to pred(DirCount) do begin if (Abort) then begin Exit; end; LI := Cnx[0].DirectoryListing[I]; if (LI.ItemType = ditFile) then begin Idx := Length(DL) + 1; SetLength(DL, Idx); J := Q mod 5; DL[Idx-1].FTP := Cnx[J]; DL[Idx-1].LI := LI; Inc(Q); end; end; { Here's the attempt at TParallel.For, to be replaced by implementing a set of TThread objects. I admit that I was learning about TParallel.For on the fly from Nick Hodges' book at 3AM.} try var LB : integer := Low(DL); var HB : integer := High(DL); TParallel.For(LB, HB, procedure(M : integer) begin try var ADL := DL[M]; if (Assigned(ADL.FTP) and Assigned(ADL.LI) and ADL.FTP.Connected) then begin ADL.FTP.Get(ADL.LI.FileName, ALocalDir + ADL.LI.FileName, True); end; except raise; end; end); except raise; end; Share this post Link to post
programmerdelphi2k 237 Posted December 2, 2022 you can see this way: client side: each thread will works like a "separated software"! then, each software should have your credencials, as well as, your file to download/upload server side: it's another history! Share this post Link to post
programmerdelphi2k 237 Posted December 2, 2022 (edited) maybe, it would be better some like this: type TMyThreadDownload = class(TThread) //.... + all definitions necessary private FileToDownload:string; // URL + filename protected procedure Execute; public constructor Create.... destructor Destroy;override.... // property FileToDownload:string read FFileToDownload write FFileToDownload; end; implementation ... other definitions constructor Create; begin FreeOnTerminate:=true; // not use MyThread.Free on button1 end; procedure TMyThreadDownload.Execute; // my sample to HTTP, but you can port it to FTP class!!! var MyClientHttp: TIdHTTP; //or any other class to downloads MyIOHandler:TIdSSLIOHandlerSocketOpenSSL; MyStream:TFileStream; begin // create IOHandler + definitions // create MyClientHtpp + definitions // create your MyStream + definitions try try MyClientHttp.Get( FFileToDownload, MyStream); // MyStream.SaveToFile('...'); except // what to do ? end; finally // release objects created end; end; then, you usage: Button1 click: var MyThread:TMyThreadDownload; begin // if you want on loop, then just loop it! // MyyThread:=TMyThreadDownload.Create; MyThread.FileToDownload:= 'xxx'; MyThread.Start; end; Edited December 2, 2022 by programmerdelphi2k Share this post Link to post