• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 721
  • Last Modified:

FTP Component

Hi,
I need an FTP component that can work Async. I've tried ICS FTP component but its putAsync method is also not working properly. Only one thread works at a time.
plz help.
0
m_adil
Asked:
m_adil
  • 23
  • 9
  • 2
  • +4
1 Solution
 
pr_wainwrightCommented:
have you tried winshoes/indy ?.
0
 
Mohammed NasmanSoftware DeveloperCommented:
Hello

did u try indy components?
http://www.nevrona.com/indy/
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
Lee_NoverCommented:
wtf ? .. did you hit refresh 8 times ?
anyway Indy is blocking
so if you want the download to run in the background create a thread and place that download there
another solution is to use the TidAntiFreeze component
it will give your apps responsivness back and allow other functions to work
but you really should go with multithreading

another option is to use f.pietes ICS components
they can work in Async or Sync
http://users.swing.be/francois.piette/icsdocuk.htm
0
 
m_adilAuthor Commented:
yes I did. but they didn't work for me either. Is there any special command/property for indy to get the file Async. ?
0
 
m_adilAuthor Commented:
Lee...
>>another option is to use f.pietes ICS components
they can work in Async or Sync

I've tried f.pietes FTP component. but it is also not working.

here is the sample code. button 1 connects the components to the FTP server and button 2 starts Async transfer. but file #2 actually starts transferring after #1 finishes.

I placed 2 FTP components on the form

procedure TForm1.Button2Click(Sender: TObject);
begin

   with FtpClient1 do
   begin
      HostName:= 'adil';
      UserName := 'anonymous';
      PassWord := 'as@as.as';
      LocalFileName := 'c:\temp\file1.exe';
      HostFileName := '/file1.exe';
      ConnectAsync;
   end;

   with FtpClient2 do
   begin
      HostName:= 'adil';
      UserName := 'anonymous';
      PassWord := 'as@as.as';
      LocalFileName := 'c:\temp\file2.exe';
      HostFileName := '/file2.exe';
      ConnectAsync;
   end;

end;


procedure TForm1.FtpClient2Progress(Sender: TObject; Count: Integer;
  var Abort: Boolean);
begin
   Gauge2.Progress :=  count*100 div 3787246;
end;

procedure TForm1.FtpClient1Progress(Sender: TObject; Count: Integer;
  var Abort: Boolean);
begin
   Gauge1.Progress :=  count*100 div 4327305;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
FtpClient1.PutAsync;
FtpClient2.PutAsync;
end;
0
 
Lee_NoverCommented:
hum
weird .. I never worked with ICS .. only Indy
you could also try TMonsterFTP
it has nice gui treeview and listview included
very simple to use
supports drag'n'drop
but in my case it didn't work well in LAN
it ended file transfers prematurelly
but it did work async as I've tested it

I'll say it again... go for Indy with Multithreading
if you do I can help you out otherwise I'm out of ideas
0
 
m_adilAuthor Commented:
ok. how can I use indy with multi threading? If you can help me out with some working ex., I will obviously increase points to 2 or 3 times.

The actual code I'm using is as follows ...

type
   TDownloadManager = Class
      FtpClient1: TFtpClient;


  private
    { Private declarations }


...... functions and procedured ......

constructor TDownloadManager.Create();
begin
   FTPClient1:= TFTPClient.Create(nil);
   FTPClient1.OnProgress := FtpClient1Progress;
   FtpClient1.OnRequestDone:= FtpClient1RequestDone;
   FtpClient1.MultiThreaded:= True;
   fsize:= -1;
   byte_cnt:= 0;
   dir_Q:= TStringList.Create;
   //busy:= False;

end;

procedure TDownloadManager.uploadFile(self_idx, list_idx:integer; r_base_folder, r_file, L_file, proxy_host, proxy_port, proxy_usr, proxy_pwd, host, port, usr, PWord: String);
var
   p: integer;
   tmp, tmp2: String;
begin

  self_id:= self_idx;
  task_id:= list_idx;

.....

end;

after calling constructor to create an instance of this class, i'm using uploadFile function to upload files.
Now how can I make this in a seprate thread? Also when doing this through indy sync, will it not choke the app till the component gets response from the FTP server?

Plz guide me how can I port this code into threads?
0
 
m_adilAuthor Commented:
one more thing ... that might be of some help for u
I'm using an array to store multiple instances of the class ... i.e.
DLoad_Manager: array[0..MAX_THREADS] of TDownloadManager;
and then calling its constructor ...
DLoad_Manager[i]:= TDownloadManager.Create;
0
 
Lee_NoverCommented:
you should store the new threads in a TThreadList
to acces the threads do :
with ThdList.LockList do
try
  for I:=0 to Count-1 do
    TDownloadThread(Items[I]).DoStuff;
finally
  ThdList.UnlockList;
end;

here's the basics to the TDownloadThread
just came home from a club so I'm a bit tired to write the whole thing
if needed I'll write it, but not now :)


-----------------------------


unit Unit2;

interface

uses
  Classes, SysUtils, IdFTP;

type
  TDownloadThread = class(TThread)
  private
    FTP: TIdFTP;
    FLocal,
    FRemote: string;
    FMode: Integer;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
    procedure UploadFile(self_idx, list_idx:integer; r_base_folder, r_file,
      L_file, proxy_host, proxy_port, proxy_usr, proxy_pwd, host, port, usr, PWord: String);
  end;

implementation


constructor TDownloadThread.Create;
begin
     inherited Create(true);
     FreeOnTerminate:=true;
     FTP:=TIdFTP.Create(nil);
end;

destructor TDownloadThread.Destroy;
begin
     FreeAndNil(FTP);
     inherited;
end;

procedure TDownloadThread.Execute;
begin
     FTP.Connect;
     if not FTP.Connected then exit;
     if FMode = 1 then
        FTP.Put(FLocal, FRemote, false)
     else
        FTP.Get(FRemote, FLocal, true, false);

     FTP.Disconnect;
end;

procedure TDownloadThread.UploadFile(self_idx, list_idx: integer;
  r_base_folder, r_file, L_file, proxy_host, proxy_port, proxy_usr,
  proxy_pwd, host, port, usr, PWord: String);
begin
     FTP.Host:=host;
     FTP.Port:=StrToIntDef(port, 21);
     FTP.Username:=usr;
     FTP.Password:=PWord;
     FLocal:=L_file;
     FRemote:=r_File;
     FMode:=1; // indicate that we're uploading
     // set all the other properties, also some progress events
     Resume; // start the thread
end;

// procedure for downloading would be similar, only set the FMode to 0 or something ...

end.
0
 
VENKATCommented:
You can try Delphi component-IntenetMailSuite-agFTP or Fastnet NMFTP components.
0
 
Lee_NoverCommented:
fastnet ??? hey you crazy ?
nobody that has a clear mind uses NM ! .. and for a good reason too
especially their ftp component
it has support for only one list format and it parses that one badly also !
not to mention other things ...
0
 
m_adilAuthor Commented:
yeah ... NM is useless...

Lee can u plz help in adding a thread in ThreadList.

should it be like...

//create thread
DLoad_Manager[i]:= TDownloadManager.Create;
List.Add(DLoad_Manager[i]);

where list is TThreadList.
0
 
m_adilAuthor Commented:
I've tried it as follows .... and its working fine.
but i just want to make sure that there isn't any problem in this code and it will work fine.

with Thread_List.LockList do
try
   DLoad_Manager[thread_idx].uploadFile(thread_idx, new_task_id, RemoteFrm.cbo_Remote_Dir.Text, remote_file, local_file, proxy_host, proxy_port, proxy_usr, proxy_pwd, host, usr, pwd, port);

finally
      Thread_List.UnlockList;
end;
0
 
Lee_NoverCommented:
you don't need a second array if you're using a ThreadList
and if you don't plan to do anything with the thread later on then there's also no need to store the threads in the list
so if you simply need to download some files then do:

procedure TForm1.UploadFile(...);
var dlThread: TDownloadThread;
begin
  dlThread:=TDownloadThread.Create;
  dlThread.UploadFile(...);
end;

the thread will be freed when it terminates
you also don't need to worry about dlThread coz it will be released when the function exists

so in this case you really don't need any lists


if you make your threads reusable then store them in the list
also don't forget to set the FreeOnTerminate:=false; in the constructor !!!
you should also change the execution method
take a look at my TlnThread base class:
http://lee.nover.has.his.evilside.org/isapi/pas2html.dll/pas2html?File=/delphi/MiscFiles/vn_common/lnVidTypes.pas

reusable threads really not needed in your case unless you tend to upload multiple files at once and all the time (like 100 files all the time)

if you go for the reusable threads I'll guide you further more :))
0
 
m_adilAuthor Commented:
Lee ... I surely want to reuse threads as there is not a fixed no of files that I've to upload/download. It could be any no (100, 1000...) so i've to reuse threads.
So I'll definately welcome your guidance in this matter :)

I'm increasing points to 100. will further increase as we get into it further.
0
 
m_adilAuthor Commented:
Lee I've tried it but the thread after finishing one take does not start the next task. Is it because the thread is already in running state and Resume call doesnot make any changes in this state. Do I need to change its state first or what ?
0
 
m_adilAuthor Commented:
Lee I've tried it but the thread after finishing one take does not start the next task. Is it because the thread is already in running state and Resume call doesnot make any changes in this state. Do I need to change its state first or what ?
0
 
m_adilAuthor Commented:
Lee I've tried it but the thread after finishing one take does not start the next task. Is it because the thread is already in running state and Resume call doesnot make any changes in this state. Do I need to change its state first or what ?
0
 
m_adilAuthor Commented:
Lee I've tried it but the thread after finishing one take does not start the next task. Is it because the thread is already in running state and Resume call doesnot make any changes in this state. Do I need to change its state first or what ?
0
 
m_adilAuthor Commented:
Lee I've tried it but the thread after finishing one take does not start the next task. Is it because the thread is already in running state and Resume call doesnot make any changes in this state. Do I need to change its state first or what ?
0
 
Lee_NoverCommented:
damn it dood .. what are you doing ?

did you take a look at the link I gave you ?
the TlnThread class has a .Run method which you need to override
in the run method you execute your upload
when you're done uploading simply call Stop;
I'll write a new descendant for you in a while
0
 
m_adilAuthor Commented:
>> I'll write a new descendant for you in a while
when will u be able to do this ?
0
 
Lee_NoverCommented:
today later on - hang on
0
 
m_adilAuthor Commented:
I'll wait for your reply for another 12 hrs and will reopen the question in case u do not reply.
0
 
Lee_NoverCommented:
oh sorry
I'm just so busy
here .. writing it now :)
0
 
Lee_NoverCommented:
ok this should work
the syntax is ok but I haven't tested if it works
it's just to demonstrate how it should be done with queuing the commands
here's the complete unit code:


unit Unit2;

interface

uses Windows, Classes, SysUtils, lnVidTypes, idFTP;

type
  TOperation = (opDownload, opUpload);

  PFtpInfo = ^TFtpInfo;
  TFtpInfo = packed record
    Host: string[255];
    Port: Word;
    User: string[32];
    Pass: string[32];
    Passive: Boolean;
  end;

  POperationInfo = ^TOperationInfo;
  TOperationInfo = packed record
    Operation: TOperation;
    LocalFile: string[255];
    RemoteFile: string[255];
    FtpInfo: TFtpInfo;
  end;

  TlnFTPThread = class(TlnThread)
  private
    FQueue: TList;
    FFTP: TidFTP;
  protected
    procedure Run; override;
  public
    constructor Create(Suspended: Boolean);
    destructor Destroy; override;
    procedure QueueFile(OperationInfo: TOperationInfo);
  end;


implementation



{ TlnFTPThread }

constructor TlnFTPThread.Create(Suspended: Boolean);
begin
     inherited Create(Suspended);
     FQueue:=TList.Create;
     FFTP:=TidFTP.Create(nil);
end;

destructor TlnFTPThread.Destroy;
var lpOI: POperationInfo;
    I: Integer;
begin
     if FQueue.Count > 0 then
        for I:=FQueue.Count-1 downto 0 do
            try
               lpOI:=FQueue.Items[I];
               Dispose(lpOI);
            except
            end;

     FreeAndNil(FQueue);
     if FFTP.Connected then
        FFTP.Disconnect;
     FreeAndNil(FFTP);
end;

procedure TlnFTPThread.QueueFile(OperationInfo: TOperationInfo);
var lpOI: POperationInfo;
begin
     New(lpOI);
     lpOI^:=OperationInfo;
     FQueue.Add(lpOI);
     Start;
end;

procedure TlnFTPThread.Run;
var lpOI: POperationInfo;
begin
     if FQueue.Count < 1 then exit;

     lpOI:=FQueue.Items[0];
     try
        try
           if FFTP.Connected then
              FFTP.Disconnect;

           FFTP.Host:=lpOI^.FtpInfo.Host;
           FFTP.Port:=lpOI^.FtpInfo.Port;
           FFTP.Username:=lpOI^.FtpInfo.User;
           FFTP.Password:=lpOI^.FtpInfo.Pass;
           FFTP.Passive:=lpOI^.FtpInfo.Passive;
           FFTP.Connect(true, 5000); // give it 5 secs to connect

           case lpOI^.Operation of
             opDownload:
             begin
               FFTP.Get(lpOI^.RemoteFile, lpOI^.LocalFile);
             end;

             opUpload:
             begin
               FFTP.Put(lpOI^.LocalFile, lpOI^.RemoteFile);
             end;
           end;

           DoNotifyWait(1, 1); // just notify of success, change this to your needs :)

        except
           on E: Exception do // failed to connect, upload, ...
              DoNotifyWait(0, Integer(PChar(E.Message)));
        end;
     finally
        Dispose(lpOI);
        FQueue.Delete(0);

        if FFTP.Connected then
           FFTP.Disconnect;
     end;
end;

end.
0
 
CleanupPingCommented:
m_adil:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0
 
Mohammed NasmanSoftware DeveloperCommented:
points to Lee_Nover
0
 
Lukasz LachCommented:
m_adil,
No comment has been added lately (11 days), so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area for this question:

RECOMMENDATION: Award points to Lee_Nover http:#7112407

Please leave any comments here within 7 days.

-- Please DO NOT accept this comment as an answer ! --

Thanks,

anAKiN
EE Cleanup Volunteer
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 23
  • 9
  • 2
  • +4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now