当前用户目录与root不同时,无法使用ftp方法重命名文件

备注:由于垃圾邮件防范机制,我被迫将Uris的开头从ftp://替换为ftp。

我有以下问题。 我必须使用C#ftp方法上传文件,然后重命名它。 容易,对吗? 🙂

好吧,假设我的ftp主机是这样的:

ftp.contoso.com

登录后,当前目录设置为:

用户/名称

所以,我想要实现的是登录,将文件作为file.ext.tmp上传到当前目录,上传成功后,将文件重命名为file.ext

正如我猜测的那样,整个难题是为FtpWebRequest正确设置请求Uri。

MSDN声明:

URI可以是相对的或绝对的。 如果URI的格式为“ ftp://contoso.com/%2fpath”(%2f是转义’/’),那么URI是绝对的,当前目录是/ path。 但是,如果URI的格式为“ ftp://contoso.com/path ”,则首先.NET Framework登录到FTP服务器(使用Credentials属性设置的用户名和密码),然后是当前目录设置为UserLoginDirectory / path。

好的,所以我使用以下URI上传文件:

ftp.contoso.com/file.ext.tmp

好的,文件落在我想要的位置:在目录“users / name”中

现在,我想重命名该文件,因此我使用以下Uri创建Web请求:

ftp.contoso.com/file.ext.tmp

并指定重命名为参数:

file.ext

这给了我550错误:找不到文件,没有权限等。

我在Microsoft网络监视器中跟踪了它,它给了我:

命令:RNFR,重命名自
CommandParameter:/file.ext.tmp
Ftp:响应端口53724,’550文件/file.ext.tmp未找到’

好像是在根目录中查找文件 – 而不是在当前目录中。

我使用Total Commander手动重命名了文件,唯一的区别是CommandParameter没有第一个斜杠:

CommandParameter:file.ext.tmp

我可以通过提供以下绝对URI来成功重命名该文件:

ftp.contoso.com/%2fusers/%2fname/file.ext.tmp

但我不喜欢这种方法,因为我必须知道当前用户目录的名称。 它可以通过使用WebRequestMethods.Ftp.PrintWorkingDirectory来完成,但它增加了额外的复杂性(调用此方法来检索目录名称,然后组合路径以形成正确的URI)。

我不明白为什么URI ftp.contoso.com/file.ext.tmp适合上传而不是重命名? 我在这里错过了什么吗?

该项目设置为.NET 4.0,在Visual Studio 2010中编码。

编辑

好的,我放置了代码片段。

请注意,应填写ftp主机,用户名和密码。 要使此示例生效 – 即产生错误 – 用户目录必须与root不同(“pwd” – 命令应返回与“/”不同的内容)

class Program { private const string fileName = "test.ext"; private const string tempFileName = fileName + ".tmp"; private const string ftpHost = "127.0.0.1"; private const string ftpUserName = "anonymous"; private const string ftpPassword = ""; private const int bufferSize = 524288; static void Main(string[] args) { try { string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName); if (!File.Exists(path)) File.WriteAllText(path, "FTP RENAME SAMPLE"); string requestUri = "ftp://" + ftpHost + "/" + tempFileName; //upload FtpWebRequest uploadRequest = (FtpWebRequest)WebRequest.Create(requestUri); uploadRequest.UseBinary = true; uploadRequest.UsePassive = true; uploadRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword); uploadRequest.KeepAlive = true; uploadRequest.Method = WebRequestMethods.Ftp.UploadFile; Stream requestStream = null; FileStream localFileStream = null; localFileStream = File.OpenRead(path); requestStream = uploadRequest.GetRequestStream(); byte[] buffer = new byte[bufferSize]; int readCount = localFileStream.Read(buffer, 0, bufferSize); long bytesSentCounter = 0; while (readCount > 0) { requestStream.Write(buffer, 0, readCount); bytesSentCounter += readCount; readCount = localFileStream.Read(buffer, 0, bufferSize); System.Threading.Thread.Sleep(100); } localFileStream.Close(); requestStream.Close(); FtpWebResponse response = (FtpWebResponse)uploadRequest.GetResponse(); FtpStatusCode code = response.StatusCode; string description = response.StatusDescription; response.Close(); if (code == FtpStatusCode.ClosingData) Console.WriteLine("File uploaded successfully"); //rename FtpWebRequest renameRequest = (FtpWebRequest)WebRequest.Create(requestUri); renameRequest.UseBinary = true; renameRequest.UsePassive = true; renameRequest.Credentials = new NetworkCredential(ftpUserName, ftpPassword); renameRequest.KeepAlive = true; renameRequest.Method = WebRequestMethods.Ftp.Rename; renameRequest.RenameTo = fileName; try { FtpWebResponse renameResponse = (FtpWebResponse)renameRequest.GetResponse(); Console.WriteLine("Rename OK, status code: {0}, rename status description: {1}", response.StatusCode, response.StatusDescription); renameResponse.Close(); } catch (WebException ex) { Console.WriteLine("Rename failed, status code: {0}, rename status description: {1}", ((FtpWebResponse)ex.Response).StatusCode, ((FtpWebResponse)ex.Response).StatusDescription); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } finally { Console.ReadKey(); } } } 

我遇到过类似的问题。 问题是FtpWebRequest(错误地)预先添加’/’来重命名请求,从此日志(上传和重命名)可以看出:

 URL: http://127.0.0.1/Test.txt FTP log: STOR Test.txt.part RNFR /Test.txt.part RNTO /Test.txt 

请注意,只有在上载到根目录时才会出现此问题。 如果您将URL更改为http://127.0.0.1/path/Test.txt ,那么一切都会正常工作。

我对这个问题的解决方案是使用%2E(点)作为路径:

 URL: http://127.0.0.1/%2E/Test.txt FTP log: STOR ./Test.txt.part RNFR ./Test.txt.part RNTO ./Test.txt 

你必须对点进行url编码,否则FtpWebRequest会将路径“/./”简化为“/”。

C#

 using System.Net; using System.IO; 

在FTP服务器function上重命名文件名

C#

  private void RenameFileName(string currentFilename, string newFilename) { FTPSettings.IP = "DOMAIN NAME"; FTPSettings.UserID = "USER ID"; FTPSettings.Password = "PASSWORD"; FtpWebRequest reqFTP = null; Stream ftpStream = null ; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + FTPSettings.IP + "/" + currentFilename)); reqFTP.Method = WebRequestMethods.Ftp.Rename; reqFTP.RenameTo = newFilename; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(FTPSettings.UserID, FTPSettings.Password); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); } catch (Exception ex) { if (ftpStream != null) { ftpStream.Close(); ftpStream.Dispose(); } throw new Exception(ex.Message.ToString()); } } public static class FTPSettings { public static string IP { get; set; } public static string UserID { get; set; } public static string Password { get; set; } }