Solved

FTP TO FTP TRANSFER?

Posted on 2004-09-28
42
954 Views
Last Modified: 2010-04-05
Does anyone knows of any algorithm, component or working solution on how to transfer files from one ftp server to another preserving paths. That means that you would have to recurse all subfolders on one ftp server and create identical directory structure on another ftp server. Please help!
0
Comment
Question by:cyberman05
  • 22
  • 15
  • 2
  • +1
42 Comments
 
LVL 11

Expert Comment

by:calinutz
ID: 12168858
It is just about copying files to a predefined structure from one server to another server? O do you have to create directories on the destination server?
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12172226
Hi,  I have found several  very infromative threads on a similar threads - have a look I am certain something there would help.

http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21070081.html#11650503
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21112532.html#11935995
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21112450.html#11932915
http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_21112408.html#11932585

between FTP's do you mean from one server to another directly ? or via another machine?  

If its between two FTP's via your machine then simply have one procedure to download the site to the hard drive and another to upload.  there are plenty of example on the above liniks

If its running on one server to change to another ... then its even easier as you can access the contents from the local hard drive and only have to access 1 FTP account

If you want more infomation, then please ask.

David Birch
0
 
LVL 4

Expert Comment

by:LMuadDIb
ID: 12174722
what you want to achive is called FXP not FTP
and I dont think there are any delphi specific components which allow you to FXP, not even sure if there are any activeX components.
funny thing is, the best fxp application ever made was made with delphi "FlashFXP"

anyway...
even if you had a delphi fxp component, I doubt it would recurse and copy the dir structure for you.
All FTP raw commands are basic in nature, and you can not get a file list with full paths. You have to recurse thru and check inside each individual folder, big pain in the butt esp if dealing with hundreds of dirs and a slow connection :-/
depending on the ftp server though, some specific ftp server  have special commands though

there are a couple things that can speed up things if you have privs:
1. if you have admin rights on the ftp server, especially execute and write access to the dirs.
You can execute a DOS command at the root of the ftp server and output the results to a text file, which you can download.
Then you can create the dirs from that file. Really fast if you have to do alot of dirs

2. Or upload an app (then execute) that will recurse and give you all the info you need

If you cant or dont want to do the above 2 things, you will have to manually do the recursing yourself Im afraid

^ENuD
0
 

Author Comment

by:cyberman05
ID: 12178276
calinutz!

yes, I want to create same directory structure on the destination ftp server.

David!

Thanks! I'll check it out later on, becouse I'm on a public computer right now. I want to transfer files from www.brinkster.com to www.web1000.com via FTP. But this is only the example URL, becouse brinkster doesn't support FTP I think, just that you get the picture what I'm trying to do. The problem is that for testing purposes I only have 2 accounts on the same ftp server. Those are cyberman05 and linear both on ftp.volja.net. Could there be a synchronisation problem when transfering files from two different ftp servers or is it better to first download file locally and then upload to second server?

LMuadIb!

Thanks for your comment too.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12181279
Could there be a synchronisation problem when transfering files from two different ftp servers or is it better to first download file locally and then upload to second server?


you are trying to do this in a Delphi program or just trying to get it done?

I would suggest that its better to download locally first for a number of reasons:
> There is a risk that the file transfur could be interupted during transfur which could cause problems
> You have a backup copy of the files for future referance
> Its easier to program as nothing has to be run on server which brinkster wouldnt allow anyway

Most normal FTP programs will allow you to download the contents of the root folders if you arent trying to do this programaticaly. I would suggest one of the sourceforge.net FTP programs.  If you want to do it with FTP then the above links have several FTP examples in them

DAvid
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12181954
Just found thos,  a working example of an FTP program in delphi :)

http://www.planet-source-code.com/vb/scripts/ShowCode.asp?lngWId=7&txtCodeId=551

though the code if for D5 - the componet is now within the indy pallette so you might have to re-work it abit

David
0
 

Author Comment

by:cyberman05
ID: 12195038
Thanks David! I want to solve the problem using Delphi. Tomorrow I'll publish my own solution. BTW there is something ilogical in your previous post. You said

"You can execute a DOS command at the root of the ftp server and output the results to a text file"

I think you can't get the whole directory structure becouse there is no ftp command that supports this. You can just list folder by folder with lst *.* command. You can't list subfolders. Or am I wrong?
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12201128
huh? when did I say that  ?

anyway no I dont think there is a command for that either, so the best solution would be to create a recurrsive function for each directory and then subdirectory downloading the files (and making the folders) in each as you go.  You might like to use a TreeView to keep a visual record on how the directory structure looks. try www.delphi-gems.com if you are interested.

David
0
 

Author Comment

by:cyberman05
ID: 12203004
OK. I've invented something of my own but there are some problems. I can only transfer root folder and only the files in first subfolder. I have to put changedir('..') somewhere but I don't know where. Any help is welcome. Can anyone fix this problem? Here is the procedure:

  public
    { Public declarations }
    FtpList_Name,FtpList_Attr,FtpList_Date,FtpList_Size : TStringList;
    LFtpList_Name,LFtpList_Attr,LFtpList_Date,LFtpList_Size : TStringList;
    BasePath : string;

procedure TForm1.Button10Click(Sender: TObject);
procedure FtpChangeDir1(path: string);
begin
// try
  NMFTP1.ChangeDir(path);
// except end;
end;

procedure FtpChangeDir2(path: string);
begin
// try
  NMFTP2.ChangeDir(path);
// except end;
end;

procedure FtpCreateDir(path: string);
begin
// try
  NMFTP2.MakeDirectory(path);
// except end;
end;

function FtpIsDirectory(FtpName: String): Boolean;
begin
  Result := FtpName[1] = 'd';
end;

procedure DownloadFile(FileName : string);
var LocalFile, RemoteFile: String;
begin
// try
  LocalFile := 'c:\temp\temp\temp3\' + FileName;
  RemoteFile := FileName;
  NMFTP1.Mode(MODE_ASCII);
  NMFTP1.Download(RemoteFile, LocalFile);
// except end;
end;

procedure UploadFile(FileName : string);
var LocalFile, RemoteFile: String;
  F: File of Byte;
  FSize: Integer;
begin
//  try
    LocalFile := 'c:\temp\temp\temp3\' + FileName;
    RemoteFile := FileName;
    NMFTP2.Mode(MODE_ASCII);
    AssignFile(F, LocalFile);
    Reset(F);
    FSize := FileSize(F);
    CloseFile(F);
    NMFTP2.Allocate(FSize);
    NMFTP2.Upload(LocalFile, RemoteFile);
//  except end;
end;

procedure FtpGetList;
begin
// try
  FtpList_Name.Clear;
  FtpList_Attr.Clear;
  FtpList_Date.Clear;
  FtpList_Size.Clear;

  NMFTP1.ParseList := True;
  NMFTP1.Vendor := NMOS_AUTO;

  NMFTP1.List;
  FtpList_Name.Text := NMFTP1.FTPDirectoryList.Name.Text;
  FtpList_Attr.Text := NMFTP1.FTPDirectoryList.Attribute.Text;
  FtpList_Date.Text := NMFTP1.FTPDirectoryList.ModifDate.Text;
  FtpList_Size.Text := NMFTP1.FTPDirectoryList.Size.text
// except end;
end;

procedure Recurse(path : string);
var i : integer;
    file_name : string;
begin
  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      DownloadFile(file_name);
      UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;
end;

procedure FtpMain;
var i : integer;
    file_name : string;
begin
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      DownloadFile(file_name);
      UploadFile(file_name);    
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;
end;
begin
  BasePath := ExtractFilePath(ExpandFileName (Application.ExeName));

  FtpList_Name := TStringList.Create;
  FtpList_Attr := TStringList.Create;
  FtpList_Date := TStringList.Create;
  FtpList_Size := TStringList.Create;

  LFtpList_Name := TStringList.Create;
  LFtpList_Attr := TStringList.Create;
  LFtpList_Date := TStringList.Create;
  LFtpList_Size := TStringList.Create;

  FtpMain;

  FtpList_Name.Free;
  FtpList_Attr.Free;
  FtpList_Date.Free;
  FtpList_Size.Free;

  LFtpList_Name.Free;
  LFtpList_Attr.Free;
  LFtpList_Date.Free;
  LFtpList_Size.Free;
end;
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203046
not sure as I havnt tested but could it be something to do with LFtpList_Name array being over written every time you cal lthe procedure recerse?  preahpsh you should take a copy of it within that procedure and then work from that ?

David
0
 

Author Comment

by:cyberman05
ID: 12203058
No, sorry David! LMuadDib said that sentence about executing a DOS command not you.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203061
hum that wasnt too clear - i mean something like this

procedure Recurse(path : string);
var i : integer;
    file_name : string;
   // add all the arrays you use  as RecurseFtpList_name ect
begin
   // copy all the arrays like into the localy declared arrays put the current values of the arrays  and then work from them

  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      DownloadFile(file_name);
      UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;
end;
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203082
this is because each time other than the first the values you are working from are over written when the recurse procedure is called
0
 

Author Comment

by:cyberman05
ID: 12203105
Damn I think you are right! Could you be more specific becouse I still don't have the idea how to fix this. I can't think much. It's 23.00 hours here. I'll read your answer tomorrow.
0
 

Author Comment

by:cyberman05
ID: 12203122
I see you are online. Ok I see you are one step in front of me with my questions. Before I ask you already answer:))
0
 

Author Comment

by:cyberman05
ID: 12203141
I'll try to correct this and let you know about the results tomorrow.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203172
lol, right recursion,

this is as you know when one procedure calls its self,

what happens is the processor stores the place of execution of the program and any LOCAL varibles to that procedure into memory and then starts at the new procedure called with a new set of varibles, when it finishes that one it goes back to where it was and calls back the old set of varibles.

In your code, the program sets up the stringlists, calls the recursion procedure which rewrites the arrays every time it is called

so what you need to do is within the procedure recurse is to create some local varibles of the same type as the orginal string lists but with different names, so that you can copy the values of the arrays, into the local varibles, so that when another procedure is called the place of execution AND the local varibles will be kept and then restored not over written as currently happens

DAvid
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203184
procedure Recurse(path : string);
var i : integer;
    file_name : string;
 RFtpList_Name,RFtpList_Attr,RFtpList_Date,RFtpList_Size : TStringList;
    RLFtpList_Name,RLFtpList_Attr,RLFtpList_Date,RLFtpList_Size : TStringList;
begin


 FtpList_Name := TStringList.Create;
  FtpList_Attr := TStringList.Create;
  FtpList_Date := TStringList.Create;
  FtpList_Size := TStringList.Create;

  LFtpList_Name := TStringList.Create;
  LFtpList_Attr := TStringList.Create;
  LFtpList_Date := TStringList.Create;
  LFtpList_Size := TStringList.Create;

  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      DownloadFile(file_name);
      UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;
end;
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12203203
ops didnt mean to hit submit - V sorry

procedure Recurse(path : string);
var i : integer;
    file_name : string;
 RFtpList_Name,RFtpList_Attr,RFtpList_Date,RFtpList_Size : TStringList;
    RLFtpList_Name,RLFtpList_Attr,RLFtpList_Date,RLFtpList_Size : TStringList;
begin


  RFtpList_Name := TStringList.Create;
  RFtpList_Attr := TStringList.Create;
  RFtpList_Date := TStringList.Create;
  RFtpList_Size := TStringList.Create;

  RLFtpList_Name := TStringList.Create;
  RLFtpList_Attr := TStringList.Create;
  RLFtpList_Date := TStringList.Create;
  RLFtpList_Size := TStringList.Create;

  for XYZ:= 0 to FtpList_Name.count-1 do RFtpList_Name[XYZ]:= FtpList_Name;
// continue for all


  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      DownloadFile(file_name);
      UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;

   FREE ALL LOCAL ARRAYS

end;
0
 
LVL 4

Expert Comment

by:LMuadDIb
ID: 12204819
---"You can execute a DOS command at the root of the ftp server and output the results to a text file"

-I think you can't get the whole directory structure becouse there is no ftp command that supports this. You can just list folder by folder with lst *.* command. You can't list subfolders. Or am I wrong?

yes, the fastest way to get a dir tree listing from an ftp server is to use a DOS command or execute any console app from the ftp server which can ouput the dir tree to a text file. Only possible if you have WRITE and EXECUTE access at the ftp server. If you dont have both, your out of luck. You execute the DOS command or app, and then download the dir tree results from the dos command. I made a console app that does that very thing. Which I can post if wanted.

You can actually execute any app for that matter via ftp if you have EXECUTE rights.
If your ftp client supports execution all you have to do is send the RAW command "site exec %f"  
%f being the app to execute with full path

the proper way would be to use recursion though, sense you can use it on any ftp server just about
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Author Comment

by:cyberman05
ID: 12208636
Much has happened here since my last visit I see. Sorry for answering so late. I had a car crash today. I knocked down a traffic light in a sober state. Anyway, LMuadDib I would appreciate if you could publish your code.

David I'll try your procedure right now. I'll finish this today even if it kills me and I don't sleep all night. Stay put.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12208762
ouch! hope your ok !

tell me how it goes

David
0
 

Author Comment

by:cyberman05
ID: 12208955
Yes I'm Ok. Luckilly I didn't kill anyone. Back to programming. Still nothing better. I can only list root folder:

drwxrwxr-x    3 5000     virtftp       176 Oct  1 18:37 Tester
-rw-rw----    1 5000     virtftp       598 Aug 31 21:23 dnsupload.txt
-rw-rw----    1 5000     virtftp    403968 Aug 23 18:03 dohodek.exe
drwxrwxr-x    2 5000     virtftp       184 Jun  3 15:55 slike
-rw-rw----    1 5000     virtftp      1278 Jun  3 15:58 software.htm

There are "slike" and "Tester" subfolders which files I can't see.

Here is the picture of application:
http://www31.brinkster.com/projekti/ftp.jpg

FTP -> FTP button is Button10 above procedure the rest is taken from Delphi help FTP sample.

Recurse procedure now looks like this:

procedure Recurse(path : string);
var i,x,y,z,k : integer;
    file_name : string;

    RFtpList_Name,RFtpList_Attr,RFtpList_Date,RFtpList_Size : TStringList;
    RLFtpList_Name,RLFtpList_Attr,RLFtpList_Date,RLFtpList_Size : TStringList;
begin
  RFtpList_Name := TStringList.Create;
  RFtpList_Attr := TStringList.Create;
  RFtpList_Date := TStringList.Create;
  RFtpList_Size := TStringList.Create;

  RLFtpList_Name := TStringList.Create;
  RLFtpList_Attr := TStringList.Create;
  RLFtpList_Date := TStringList.Create;
  RLFtpList_Size := TStringList.Create;

  for x:= 0 to FtpList_Name.count-1 do RFtpList_Name[x]:= FtpList_Name[x];
  for y:= 0 to FtpList_Attr.count-1 do RFtpList_Attr[y]:= FtpList_Attr[y];
  for z:= 0 to FtpList_Size.count-1 do RFtpList_Size[z]:= FtpList_Date[z];
  for k:= 0 to FtpList_Date.count-1 do RFtpList_Date[k]:= FtpList_Size[k];

  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to LFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(LFtpList_Attr[i]) Then
     begin
      file_name := LFtpList_Name[i];
      //DownloadFile(file_name);
      //UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(LFtpList_Name[i]);
      Recurse(LFtpList_Name[i]);
     end;
  End;

  RFtpList_Name.Free;
  RFtpList_Attr.Free;
  RFtpList_Date.Free;
  RFtpList_Size.Free;

  RLFtpList_Name.Free;
  RLFtpList_Attr.Free;
  RLFtpList_Date.Free;
  RLFtpList_Size.Free;

end;

I can send you the whole application by email if you want but without passwords.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12209106
no need to send the project, hopefuly all you need to do is add this

  for x:= 0 to LFtpList_Name.count-1 do RLFtpList_Name[x]:= LFtpList_Name[x];
  for y:= 0 to LFtpList_Attr.count-1 do RLFtpList_Attr[y]:= LFtpList_Attr[y];
  for z:= 0 to LFtpList_Size.count-1 do RLFtpList_Size[z]:= LFtpList_Date[z];
  for k:= 0 to LFtpList_Date.count-1 do RLFtpList_Date[k]:= L FtpList_Size[k];

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  RLFtpList_Name.Text := FtpList_Name.Text;
  RLFtpList_Attr.Text := FtpList_Attr.Text;
  RLFtpList_Date.Text := FtpList_Date.Text;
  RLFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to RLFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(RLFtpList_Attr[i]) Then
     begin
      file_name := RLFtpList_Name[i];
      //DownloadFile(file_name);
      //UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(RLFtpList_Name[i]);
      Recurse(RLFtpList_Name[i]);
     end;
  End;


So that you use the local vairbles, which wont be over written when other procedures are called

David
0
 

Author Comment

by:cyberman05
ID: 12209501
Still nothing better.

procedure Recurse(path : string);
var i,x,y,z,k : integer;
    file_name : string;

    RFtpList_Name,RFtpList_Attr,RFtpList_Date,RFtpList_Size : TStringList;
    RLFtpList_Name,RLFtpList_Attr,RLFtpList_Date,RLFtpList_Size : TStringList;
begin
  RFtpList_Name := TStringList.Create;
  RFtpList_Attr := TStringList.Create;
  RFtpList_Date := TStringList.Create;
  RFtpList_Size := TStringList.Create;

  RLFtpList_Name := TStringList.Create;
  RLFtpList_Attr := TStringList.Create;
  RLFtpList_Date := TStringList.Create;
  RLFtpList_Size := TStringList.Create;

  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList;

  for x:= 0 to LFtpList_Name.count-1 do RLFtpList_Name[x]:= LFtpList_Name[x];
  for y:= 0 to LFtpList_Attr.count-1 do RLFtpList_Attr[y]:= LFtpList_Attr[y];
  for z:= 0 to LFtpList_Size.count-1 do RLFtpList_Size[z]:= LFtpList_Date[z];
  for k:= 0 to LFtpList_Date.count-1 do RLFtpList_Date[k]:= LFtpList_Size[k];

  LFtpList_Name.Text := FtpList_Name.Text;
  LFtpList_Attr.Text := FtpList_Attr.Text;
  LFtpList_Date.Text := FtpList_Date.Text;
  LFtpList_Size.Text := FtpList_Size.Text;

  RLFtpList_Name.Text := FtpList_Name.Text;
  RLFtpList_Attr.Text := FtpList_Attr.Text;
  RLFtpList_Date.Text := FtpList_Date.Text;
  RLFtpList_Size.Text := FtpList_Size.Text;

  For i := 0 to RLFtpList_Name.Count-1 do
  Begin
    If not FtpIsDirectory(RLFtpList_Attr[i]) Then
     begin
      file_name := RLFtpList_Name[i];
      //DownloadFile(file_name);
      //UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(RLFtpList_Name[i]);
      Recurse(RLFtpList_Name[i]);
     end;
  End;

  RFtpList_Name.Free;
  RFtpList_Attr.Free;
  RFtpList_Date.Free;
  RFtpList_Size.Free;

  RLFtpList_Name.Free;
  RLFtpList_Attr.Free;
  RLFtpList_Date.Free;
  RLFtpList_Size.Free;
end;
0
 

Author Comment

by:cyberman05
ID: 12209541
Damn! It works so unreliably. I added showmessage(path); on FtpChangeDir1 and it works totally different. Now I get subscript out of range in FtpMain procedure on call to Recurse procedure. No sense. I'll try to put the output to a file for debugging purposes. I'm going to sleep now.
0
 

Author Comment

by:cyberman05
ID: 12209599
Ok, here is the problem. First the FtpMain procedure is called, than FtpGetList procedure is called from inside of FtpMain and from within FetGetList procedure code is executed up until the line   NMFTP1.List; and there it all stops. RECURSE PROCEDURE IS NOT EVEN CALLED!
0
 

Author Comment

by:cyberman05
ID: 12209623
here you can see the whole unit:

http://users.volja.net/cyberman05/Unit1.pas
0
 

Author Comment

by:cyberman05
ID: 12209625
LMuadDib please if you have any reliable solution please publish it.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12210525
Whilst the procedure FTPMain is in use its vairibles are over writen just likke what happened with the recourse


(also your show message within that should be showmessage(RLFtpList_Name[i]);)

David
0
 

Author Comment

by:cyberman05
ID: 12211166
I thought so. I'll correct this in every procedure possible. I wonder if it will do any good. I'll let you know.
0
 

Author Comment

by:cyberman05
ID: 12211337
Ok, now I think there is no single thing that can be overwritten any more, but still everything stops on NMFTP1.List. Here is how it look now:

procedure FtpGetList1;
begin
// try
  FtpList_Name1.Clear;
  FtpList_Attr1.Clear;
  FtpList_Date1.Clear;
  FtpList_Size1.Clear;

  NMFTP1.ParseList := True;
  NMFTP1.Vendor := NMOS_AUTO;

  NMFTP1.List;
  showmessage('smo mimo');
  FtpList_Name1.Text := NMFTP1.FTPDirectoryList.Name.Text;
  FtpList_Attr1.Text := NMFTP1.FTPDirectoryList.Attribute.Text;
  FtpList_Date1.Text := NMFTP1.FTPDirectoryList.ModifDate.Text;
  FtpList_Size1.Text := NMFTP1.FTPDirectoryList.Size.text
// except end;
end;

procedure FtpGetList2;
begin
// try
  FtpList_Name2.Clear;
  FtpList_Attr2.Clear;
  FtpList_Date2.Clear;
  FtpList_Size2.Clear;

  NMFTP1.ParseList := True;
  NMFTP1.Vendor := NMOS_AUTO;

  NMFTP1.List;
  FtpList_Name2.Text := NMFTP1.FTPDirectoryList.Name.Text;
  FtpList_Attr2.Text := NMFTP1.FTPDirectoryList.Attribute.Text;
  FtpList_Date2.Text := NMFTP1.FTPDirectoryList.ModifDate.Text;
  FtpList_Size2.Text := NMFTP1.FTPDirectoryList.Size.text
// except end;
end;

procedure Recurse(path : string);
var i,x,y,z,k : integer;
    file_name : string;

    RFtpList_Name2,RFtpList_Attr2,RFtpList_Date2,RFtpList_Size2 : TStringList;
    RLFtpList_Name2,RLFtpList_Attr2,RLFtpList_Date2,RLFtpList_Size2 : TStringList;
begin
  RFtpList_Name2 := TStringList.Create;
  RFtpList_Attr2 := TStringList.Create;
  RFtpList_Date2 := TStringList.Create;
  RFtpList_Size2 := TStringList.Create;

  RLFtpList_Name2 := TStringList.Create;
  RLFtpList_Attr2 := TStringList.Create;
  RLFtpList_Date2 := TStringList.Create;
  RLFtpList_Size2 := TStringList.Create;

  FtpChangeDir1(path);
  FtpChangeDir2(path);
  FtpGetList2;

  LFtpList_Name2.Text := FtpList_Name2.Text;
  LFtpList_Attr2.Text := FtpList_Attr2.Text;
  LFtpList_Date2.Text := FtpList_Date2.Text;
  LFtpList_Size2.Text := FtpList_Size2.Text;

  for x:= 0 to LFtpList_Name2.count-1 do RLFtpList_Name2[x]:= LFtpList_Name2[x];
  for y:= 0 to LFtpList_Attr2.count-1 do RLFtpList_Attr2[y]:= LFtpList_Attr2[y];
  for z:= 0 to LFtpList_Size2.count-1 do RLFtpList_Size2[z]:= LFtpList_Date2[z];
  for k:= 0 to LFtpList_Date2.count-1 do RLFtpList_Date2[k]:= LFtpList_Size2[k];

  For i := 0 to RLFtpList_Name2.Count-1 do
  Begin
    If not FtpIsDirectory(RLFtpList_Attr2[i]) Then
     begin
      file_name := RLFtpList_Name2[i];
      //DownloadFile(file_name);
      //UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(RLFtpList_Name2[i]);
      Recurse(RLFtpList_Name2[i]);
     end;
  End;

  RFtpList_Name2.Free;
  RFtpList_Attr2.Free;
  RFtpList_Date2.Free;
  RFtpList_Size2.Free;

  RLFtpList_Name2.Free;
  RLFtpList_Attr2.Free;
  RLFtpList_Date2.Free;
  RLFtpList_Size2.Free;
end;

procedure FtpMain;
var i,x,y,z,k : integer;
    file_name : string;

    RFtpList_Name1,RFtpList_Attr1,RFtpList_Date1,RFtpList_Size1 : TStringList;
    RLFtpList_Name1,RLFtpList_Attr1,RLFtpList_Date1,RLFtpList_Size1 : TStringList;
begin
  RFtpList_Name1 := TStringList.Create;
  RFtpList_Attr1 := TStringList.Create;
  RFtpList_Date1 := TStringList.Create;
  RFtpList_Size1 := TStringList.Create;

  RLFtpList_Name1 := TStringList.Create;
  RLFtpList_Attr1 := TStringList.Create;
  RLFtpList_Date1 := TStringList.Create;
  RLFtpList_Size1 := TStringList.Create;

  FtpGetList1;

  LFtpList_Name1.Text := FtpList_Name1.Text;
  LFtpList_Attr1.Text := FtpList_Attr1.Text;
  LFtpList_Date1.Text := FtpList_Date1.Text;
  LFtpList_Size1.Text := FtpList_Size1.Text;

  for x:= 0 to LFtpList_Name1.count-1 do RLFtpList_Name1[x]:= LFtpList_Name1[x];
  for y:= 0 to LFtpList_Attr1.count-1 do RLFtpList_Attr1[y]:= LFtpList_Attr1[y];
  for z:= 0 to LFtpList_Size1.count-1 do RLFtpList_Size1[z]:= LFtpList_Date1[z];
  for k:= 0 to LFtpList_Date1.count-1 do RLFtpList_Date1[k]:= LFtpList_Size1[k];

  For i := 0 to RLFtpList_Name1.Count-1 do
  Begin
    If not FtpIsDirectory(RLFtpList_Attr1[i]) Then
     begin
      file_name := RLFtpList_Name1[i];
      //DownloadFile(file_name);
      //UploadFile(file_name);
     end
    else
     begin
      FtpCreateDir(RLFtpList_Name1[i]);
      Recurse(RLFtpList_Name1[i]);
     end;
  End;

  RFtpList_Name1.Free;
  RFtpList_Attr1.Free;
  RFtpList_Date1.Free;
  RFtpList_Size1.Free;

  RLFtpList_Name1.Free;
  RLFtpList_Attr1.Free;
  RLFtpList_Date1.Free;
  RLFtpList_Size1.Free;
end;
begin
  BasePath := ExtractFilePath(ExpandFileName (Application.ExeName));

  FtpList_Name1 := TStringList.Create;
  FtpList_Attr1 := TStringList.Create;
  FtpList_Date1 := TStringList.Create;
  FtpList_Size1 := TStringList.Create;

  LFtpList_Name1 := TStringList.Create;
  LFtpList_Attr1 := TStringList.Create;
  LFtpList_Date1 := TStringList.Create;
  LFtpList_Size1 := TStringList.Create;

  FtpList_Name2 := TStringList.Create;
  FtpList_Attr2 := TStringList.Create;
  FtpList_Date2 := TStringList.Create;
  FtpList_Size2 := TStringList.Create;

  LFtpList_Name2 := TStringList.Create;
  LFtpList_Attr2 := TStringList.Create;
  LFtpList_Date2 := TStringList.Create;
  LFtpList_Size2 := TStringList.Create;

  FtpMain;

  FtpList_Name1.Free;
  FtpList_Attr1.Free;
  FtpList_Date1.Free;
  FtpList_Size1.Free;

  LFtpList_Name1.Free;
  LFtpList_Attr1.Free;
  LFtpList_Date1.Free;
  LFtpList_Size1.Free;

  FtpList_Name2.Free;
  FtpList_Attr2.Free;
  FtpList_Date2.Free;
  FtpList_Size2.Free;

  LFtpList_Name2.Free;
  LFtpList_Attr2.Free;
  LFtpList_Date2.Free;
  LFtpList_Size2.Free;
end;

I think this is not going anywhere. We need a different approach.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12211405
ok I shall try to explain it again,

when you use recursion, what happens is that when the procedure is called, a new instance of the procedure is created with new local varibles, if the procedure then calls its self, (recursion) a new instance is created with new varibles.  

have a read of this:

http://personal.vsnl.com/erwin/recursion.htm

could you e-mail me the whole prject? im a bit lost ;) web        @      davidbirch2.com

David
0
 

Author Comment

by:cyberman05
ID: 12213380
I've send you an email. Hope you have recived it.
0
 

Author Comment

by:cyberman05
ID: 12216555
David are you still alive? I haven't heard from you for a ling time.
0
 

Author Comment

by:cyberman05
ID: 12218003
Know what? I've checked out Francois Piette components on www.overbyte.be. The problem is that the list process should run asynchroneously as in Piette's components. Another thing is that my recursion algorithm is wrong since it will only recurse the first subfolder. I need another recursion algorithm.
0
 
LVL 7

Expert Comment

by:DavidBirch2dotCom
ID: 12218126
sorry Ive been working all day....  I havnt recieved you e-mail ?

tell me how it goes and if you need some more help

David
0
 

Accepted Solution

by:
cyberman05 earned 0 total points
ID: 12221494
I knew it. I'm having trouble with the internet connection. I'll send you again tomorrow from another computer. Anyway I'm writing a new recursion procedure. I think it should look something like this:

type Direktorij = Record
       Parent : integer;
       Child : integer;
       ChildName : string;
end;

var
  MainForm: TMainForm;
  Dirs : array of Direktorij;

procedure Recurse(numParent,numChild: integer; strpath:string);
var SearchRec : TSearchRec;
    Found : integer;
    str:TStringList;
begin
  str:=TStringList.Create;
  Found:=FindFirst(strpath,FaAnyFile,SearchRec);
  while (Found=0) do
  begin
    if (SearchRec.Attr and faDirectory = faDirectory) then
      begin
       str.add(SearchRec.Name);
       Dirs[x].Parent:=numParent;
       Dirs[x].Child:=numChild;
       Dirs[x].ChildName:=SearchRec.Name;
       x:=x+1;
      end
    else
      begin
       str.add(SearchRec.Name);
      end;
    Found:=FindNext(SearchRec);
  end;
  memo1.lines.assign(str);
  memo1.lines.add('');
  str.free;
end;

On the Dirs[x].Parent:=numParent; Access violation error occurs but I don't know why?
0
 

Author Comment

by:cyberman05
ID: 12224911
Ok, mail has been send again. Now you must have recived it becouse I've send it via yahoo.
0
 

Author Comment

by:cyberman05
ID: 12234442
Administrators, I want this topic closed and points refunded becouse I want to open a new topic "Recursion tree".
For anyone who would try to solve this ftp to ftp problem I suggest using Piette's FTP components (www.overbyte.be) to recurse and transfer files via ftp , becouse they work asynchroneously. The main problem is good recursion algorithm.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now