我有一个程序需要在FTP服务器上将文件从一个目录移动到另一个目录。例如,文件位于:
ftp://1.1.1.1/MAIN/Dir1
我需要将文件移动到:
ftp://1.1.1.1/MAIN/Dir2
我发现有几篇文章建议使用Rename命令,所以我尝试了以下内容:
Uri serverFile = new Uri(“ftp://1.1.1.1/MAIN/Dir1/MyFile.txt");
FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.RenameTo = “ftp://1.1.1.1/MAIN/Dir2/MyFile.txt";
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
但这似乎不起作用 - 我收到以下错误:
远程服务器返回错误:(550)文件不可用(例如,找不到文件,无法访问)。
起初我认为这可能与权限有关,但据我所知,我拥有整个FTP站点的权限(它在我的本地PC上,并且uri被解析为localhost)。
是否可以在这样的目录之间移动文件,如果没有,怎么可能?
要解决已提出的一些观点/建议:
此外,我已尝试将目录路径设置为:
ftp://1.1.1.1/%2fMAIN/Dir1/MyFile.txt
源路径和目标路径 - 但这也没有区别。
我发现this文章,似乎说将目的地指定为相对路径会有所帮助 - 似乎无法将绝对路径指定为目的地。
reqFTP.RenameTo = “../Dir2/MyFile.txt";
答案 0 :(得分:18)
遇到同样的问题,找到了解决问题的另一种方法:
public string FtpRename( string source, string destination ) {
if ( source == destination )
return;
Uri uriSource = new Uri( this.Hostname + "/" + source ), UriKind.Absolute );
Uri uriDestination = new Uri( this.Hostname + "/" + destination ), UriKind.Absolute );
// Do the files exist?
if ( !FtpFileExists( uriSource.AbsolutePath ) ) {
throw ( new FileNotFoundException( string.Format( "Source '{0}' not found!", uriSource.AbsolutePath ) ) );
}
if ( FtpFileExists( uriDestination.AbsolutePath ) ) {
throw ( new ApplicationException( string.Format( "Target '{0}' already exists!", uriDestination.AbsolutePath ) ) );
}
Uri targetUriRelative = uriSource.MakeRelativeUri( uriDestination );
//perform rename
FtpWebRequest ftp = GetRequest( uriSource.AbsoluteUri );
ftp.Method = WebRequestMethods.Ftp.Rename;
ftp.RenameTo = Uri.UnescapeDataString( targetUriRelative.OriginalString );
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
return response.StatusDescription;
}
答案 1 :(得分:12)
MSDN似乎表明您的路径被认为是相对路径,因此它尝试使用提供的凭据登录到FTP服务器,然后将当前目录设置为<UserLoginDirectory>/path
目录。如果这与您的文件所在的目录不同,则会出现550错误。
答案 2 :(得分:2)
在下面的代码示例中,我尝试使用以下数据并且它可以正常工作。
FTP登录位置为&#34; C:\ FTP&#34;。
文件原始位置&#34; C:\ FTP \ Data \ FTP.txt&#34;。
要移动的文件,&#34; C:\ FTP \ Move \ FTP.txt&#34;。
Uri serverFile = new Uri(“ftp://localhost/Data/FTP.txt");
FtpWebRequest reqFTP= (FtpWebRequest)FtpWebRequest.Create(serverFile);
reqFTP.Method = WebRequestMethods.Ftp.Rename;
reqFTP.Credentials = new NetworkCredential(ftpUser, ftpPass);
reqFTP.RenameTo = “../Move/FTP.txt";
FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
答案 3 :(得分:1)
我能够使用它,但只能使用服务器上存在的路径,即RenameTo中的/DRIVELETTER:/FOLDERNAME/filename
=“
答案 4 :(得分:1)
如果您只有绝对路径怎么办?
好的,我发现这篇文章是因为我收到了同样的错误。答案似乎是使用相对路径,这不是很好的解决我的问题,因为我将文件夹路径作为绝对路径字符串。
我在飞行工作中提出的解决方案但至少可以说是丑陋的。我会将此作为社区wiki的答案,如果有人有更好的解决方案,请随时编辑。
自从我了解到这一点后,我有两个解决方案。
从移动到路径的绝对路径,并将其转换为相对URL。
public static string GetRelativePath(string ftpBasePath, string ftpToPath)
{
if (!ftpBasePath.StartsWith("/"))
{
throw new Exception("Base path is not absolute");
}
else
{
ftpBasePath = ftpBasePath.Substring(1);
}
if (ftpBasePath.EndsWith("/"))
{
ftpBasePath = ftpBasePath.Substring(0, ftpBasePath.Length - 1);
}
if (!ftpToPath.StartsWith("/"))
{
throw new Exception("Base path is not absolute");
}
else
{
ftpToPath = ftpToPath.Substring(1);
}
if (ftpToPath.EndsWith("/"))
{
ftpToPath = ftpToPath.Substring(0, ftpToPath.Length - 1);
}
string[] arrBasePath = ftpBasePath.Split("/".ToCharArray());
string[] arrToPath = ftpToPath.Split("/".ToCharArray());
int basePathCount = arrBasePath.Count();
int levelChanged = basePathCount;
for (int iIndex = 0; iIndex < basePathCount; iIndex++)
{
if (arrToPath.Count() > iIndex)
{
if (arrBasePath[iIndex] != arrToPath[iIndex])
{
levelChanged = iIndex;
break;
}
}
}
int HowManyBack = basePathCount - levelChanged;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < HowManyBack; i++)
{
sb.Append("../");
}
for (int i = levelChanged; i < arrToPath.Count(); i++)
{
sb.Append(arrToPath[i]);
sb.Append("/");
}
return sb.ToString();
}
public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename)
{
string retval = string.Empty;
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftpfrompath + filename);
ftp.Method = WebRequestMethods.Ftp.Rename;
ftp.Credentials = new NetworkCredential(username, password);
ftp.UsePassive = true;
ftp.RenameTo = GetRelativePath(ftpfrompath, ftptopath) + filename;
Stream requestStream = ftp.GetRequestStream();
FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse();
Stream responseStream = ftpresponse.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
...或
从“ftp from”路径下载文件,将其上传到“ftp to”路径并从“ftp from”路径中删除。
public static string SendFile(string ftpuri, string username, string password, string ftppath, string filename, byte[] datatosend)
{
if (ftppath.Substring(ftppath.Length - 1) != "/")
{
ftppath += "/";
}
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename);
ftp.Method = WebRequestMethods.Ftp.UploadFile;
ftp.Credentials = new NetworkCredential(username, password);
ftp.UsePassive = true;
ftp.ContentLength = datatosend.Length;
Stream requestStream = ftp.GetRequestStream();
requestStream.Write(datatosend, 0, datatosend.Length);
requestStream.Close();
FtpWebResponse ftpresponse = (FtpWebResponse)ftp.GetResponse();
return ftpresponse.StatusDescription;
}
public static string DeleteFile(string ftpuri, string username, string password, string ftppath, string filename)
{
FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpuri + ftppath + filename);
ftp.Method = WebRequestMethods.Ftp.DeleteFile;
ftp.Credentials = new NetworkCredential(username, password);
ftp.UsePassive = true;
FtpWebResponse response = (FtpWebResponse)ftp.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
public static string MoveFile(string ftpuri, string username, string password, string ftpfrompath, string ftptopath, string filename)
{
string retval = string.Empty;
byte[] filecontents = GetFile(ftpuri, username, password, ftpfrompath, filename);
retval += SendFile(ftpuri, username, password, ftptopath, filename, filecontents);
retval += DeleteFile(ftpuri, username, password, ftpfrompath, filename);
return retval;
}
答案 5 :(得分:0)
您是否在FTP服务中定义了这些文件夹? FTP服务是否正在运行?如果任一问题的答案为否,则无法使用FTP移动文件。
尝试在FTP客户端中打开FTP文件夹,看看会发生什么。如果您仍然有错误,则定义有问题,因为FTP服务没有看到该文件夹,或者文件夹在逻辑上不在您认为它在FTP服务中的位置。
您还可以打开IIS管理器并查看FTP中的设置方式。
对于移动文件的其他方法,只要程序运行的帐户具有适当的权限,您就可以轻松地从UNC路径移动到另一个路径。 UNC路径类似于HTTP或FTP路径,方向相反,没有指定协议。
答案 6 :(得分:0)
代码看起来正确。所以要么你有错误的路径,文件DOESNT存在或你需要尊重案例(显然Windows不区分大小写,但Linux,Unix是)。
您是否尝试在浏览器中打开文件?打开Windows文件资源管理器,在路径栏中键入地址,看看你得到了什么。
答案 7 :(得分:-1)
U可以使用以下代码:
文件原始位置“ ftp://example.com/directory1/Somefile.file”。
要移动的文件“ /newDirectory/Somefile.file”。
请注意,目标网址不需要以ftp://example.com
开头NetworkCredential User = new NetworkCredential("UserName", "password");
FtpWebRequest Wr =FtpWebRequest)FtpWebRequest.Create("ftp://Somwhere.com/somedirectory/Somefile.file");
Wr.UseBinary = true;
Wr.Method = WebRequestMethods.Ftp.Rename;
Wr.Credentials = User;
Wr.RenameTo = "/someotherDirectory/Somefile.file";
back = (FtpWebResponse)Wr.GetResponse();
bool Success = back.StatusCode == FtpStatusCode.CommandOK || back.StatusCode == FtpStatusCode.FileActionOK;
答案 8 :(得分:-2)
我正在研究相同类型的项目,尝试构建一个可以移动文件并在文件所在的服务器上运行的Web服务。使用参数构建它以传入文件名。在开始编写文件时,您可能希望在文件名中附加一个值,例如与文件相关的数据的PK等。