简体   繁体   中英

Move a file to another Ftp directory and rename it

I've been struggling with that for the past few hours and I literally can't find a way to do it without downloading and uploading the file again. Is it even possible?

This question is kind of a copy of this one: How can I use FTP to move files between directories? but I have the feeling that its not solved, although it's answered.

Renaming the file itself is quite easy and works without any problems, but how do I move it to another directory?

I have this sample code:

string uri2 = "ftp://ftpUser@testFtp.com/mainFolder/moveFrom/file.txt";

f = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri2));

f.Credentials = new NetworkCredential(ftpUser, ftpPass);
f.KeepAlive = false;
f.UsePassive = true;
f.Method = WebRequestMethods.Ftp.Rename;
f.Timeout = 5000;
f.UseBinary = true;

f.RenameTo = "ftp://ftpUser@testFtp.com/mainFolder/moveTo/file.txt";

FtpWebResponse response = (FtpWebResponse)f.GetResponse();

response.Close();
f.Abort();

I get the same error as in the other topic:

The remote server returned an error: (550) File unavailable (eg, file not found, no access).

Using a relative path, doesn't do anything different.

Do I do something wrong or is the only way to download from the source folder, upload to dest and then delete the file from the source? That's 3 calls to the FTP server..

.NET puts an abstraction layer over the FTP protocol which can abstract too much away and thus makes some things impossible or tricky. I did not have a source code of .NET, but based on the source of FTPWebRequest from Mono (an implementation which tries to be compatible with .NET) it will do for any operations on URIs:

  • Split first the URI into a directory part and a file_name part (see CWDAndSetFileName in source).
  • CWD to the directory.
  • And do the operation there.

With renaming URL=ftp:/host/foo/bar/file1 to RenameTo=file2 this means in FTP commands:

... log into host ...
CWD foo/bar
RNFR file1
RNTO file2

But, if you have source and target in different directories, eg RenameTo=/foo/bar2/file2 , you would rather have it like this:

... log into host ...
RNFR foo/bar/file1
RNTO foo/bar2/file2

But unfortunately that is not the way it is implemented :(

If you are lucky you could try to use a relative path, eg RenameTo=../bar2/file2 , which should result in

... log into host ...
CWD foo/bar
RNFR file1
RNTO ../bar2/file2

This should probably work with the Mono-Implementation, but I don't know if it also works with real .NET.

Edit: I just had a look at the source for .NET 4.5 . It differs from Mono in that it does not do a CWD to the basedir before the file operation, but instead prepends the current basedir to the name if the name is relative. Thus with renameTo=../bar2/file2 this results in

 RNFR foo/bar/file1
 RNTO foo/bar/../bar2/file2

while with an absolute name renameTo=/bar2/file2 this would result in

 RNFR foo/bar/file1
 RNTO /bar2/file2

Depending on type and setup of the FTP server the absolute name might get interpreted as relative to the root of the users home directory, or it might be a real absolute path. So it would be best to work only with relative path and the solution with ../dir/ should work with Mono and "real" .NET.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM