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 (e.g., 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:
file_name
part (see CWDAndSetFileName
in source).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, e.g. 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, e.g. 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.