Geeks With Blogs

Lance's TextBox

Every so often I get a question from someone who wants to transfer files between two FTP servers.  In order to do so, they usually have to connect to server 1, download the files, and then connect to server 2 and upload the files.  The process could go much sooner if they could eliminate the extra transfers and just copy the files directly from server 1 to server 2.  It turns out this is possible, and is in fact mentioned in the FTP spec (RFC 959), but most people don't realize it.  Also most servers don't allow it by default, for security reasons.

FXP, aka site-to-site transfer, aka server-to-server transfer is really just a sneaky trick of the FTP protocol itself.  Here's how FXP works:

  1. Create a connection to FTP server 1, and another connection to FTP server 2. 
  2. On FTP server 1, enter passive mode (data connections will be incoming), and make a note of the servers response to the PASV command (what ip the server will be listening on, and on what port). 
  3. On server 2, send a PORT command (data connections will be outgoing), such that the port command data corresponds to the data in FTP server 1's reply to the PASV command gathered in step 2. 
  4. Finally, send the STOR command to ftp server 1, and the RETR command to FTP server 2.  The data connection will be made between those two servers, and when the transfer is complete the client will be notified by

Here's how you can do this with two instances of the IPWorks FTP component:

   1:      public void FXP()
   2:      {
   3:        //FXP, aka site-to-site or server-to-server transfers
   4:        //not commonly supported by FTP servers by default, for
   5:        //security reasons
   7:        string[] portdata = null;
   8:        Ftp ftpA = new Ftp();
   9:        ftpA.Timeout = 5;
  10:        ftpA.OnPITrail += new Ftp.OnPITrailHandler(delegate(object sender, FtpPITrailEventArgs e)
  11:        {
  12:          if (e.Message.StartsWith("227")) //response to PASV
  13:          {
  14:            string portparams = e.Message.Substring(e.Message.IndexOf("(") + 1);
  15:            portparams = portparams.Remove(portparams.IndexOf(")"));
  16:            portdata = portparams.Split(new char[] { ',' });
  17:          }
  18:        });
  19:        ftpA.RemoteHost = "serverA";
  20:        ftpA.User = "test";
  21:        ftpA.Password = "password";
  22:        ftpA.Passive = true;
  23:        ftpA.Logon();
  24:        ftpA.Command = "PASV";
  25:        //if this reply was 200 OK, then the server will allow the site to site transfer.
  27:        //now we know the port number that server A is listening on (portparams),
  28:        //so start a retriever on server B:
  29:        ThreadPool.QueueUserWorkItem(new WaitCallback(FTPRetriever), portdata);
  31:        //start the sender on server A:
  32:        ftpA.Command = "STOR uploaded.txt\r\n"; //the file to create on server 1
  34:        //done..disconnect
  35:        ftpA.Logoff();
  36:      }
  38:      static void FTPRetriever(object parameter)
  39:      {
  40:        string[] portdata = (string[])parameter;
  41:        Ftp ftpB = new Ftp();
  42:        ftpB.Timeout = 5;
  43:        ftpB.RemoteHost = "serverB";
  44:        ftpB.User = "test";
  45:        ftpB.Password = "mypassword";
  46:        ftpB.Passive = false;
  47:        ftpB.Logon();
  48:        ftpB.RemotePath = "destinationfolder/";
  49:        ftpB.ListDirectory();
  51:        ftpB.Command = "PORT " + portdata[0] + "," + portdata[1] + "," + portdata[2] + "," + 
  52:                                     portdata[3] + "," + portdata[4] + "," + portdata[5];
  53:        ftpB.Command = "RETR uploaded.txt"; //the file to get from server A
  54:        ftpB.Logoff();
  55:      }


There you have it, a pretty straight forward process.  ftpA connects to server A and sends the command needed to create an incoming data transfer connection and start sending a file called uploaded.txt.  ftpB connects to server B and sends the commands needed to create an outgoing data transfer connection (to server A) and receive the file uploaded.txt.

Technorati Tags: , ,
Posted on Thursday, May 15, 2008 12:02 PM Programming | Back to top

Comments on this post: FXP - FTP transfers from server to server

# Mr
Requesting Gravatar...
Thanks so much for this script. If it works, will save my tons of time. I am going to use it now. Will post again. If it works for me.
Left by Raj Hasan on Dec 05, 2010 10:39 AM

# re: FXP - FTP transfers from server to server
Requesting Gravatar...
Currently i have two FXP server connecting to two diverse location at least across 7 hops (through a fiber connection 80km away) and two firewalls. I have two file transfer protocol (CIFS and FXP). When i am transferring this file across, the transfer rate on CIFS take an average 52min meanwhile on FPX it takes 7 to 11 hours!. The FXP command somehow seems to be waiting for a transfer acknowledgement upon completion. If there any command that we need to add on the firewall to pass this command to the client / host server ?
Left by Prakash on Aug 29, 2017 10:39 PM

Your comment:
 (will show your gravatar)

Copyright © Lance Robinson | Powered by: