23

我有一个程序需要在 FTP 服务器上将文件从一个目录移动到另一个目录。例如,该文件位于:

ftp://1.1.1.1/MAIN/Dir1

我需要将文件移动到:

ftp://1.1.1.1/MAIN/Dir2

我发现了几篇推荐使用重命名命令的文章,所以我尝试了以下方法:

    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)。

是否可以像这样在目录之间移动文件,如果没有,怎么可能?

为了解决已经提出的一些观点/建议:

  1. 我可以从源目录下载相同的文件,所以它肯定存在(我正在做的是先下载文件,然后将其移动到其他地方)。
  2. 我可以从浏览器(源目录和目标目录)访问 ftp 站点
  3. ftp 服务器在我本地机器上我自己的 IIS 实例下运行。
  4. 路径和大小写正确,没有特殊字符。

此外,我尝试将目录路径设置为:

ftp://1.1.1.1/%2fMAIN/Dir1/MyFile.txt

对于源路径和目标路径 - 但这也没有区别。

我找到了这篇文章,它似乎说将目标指定为相对路径会有所帮助 - 似乎无法将绝对路径指定为目标。

reqFTP.RenameTo = “../Dir2/MyFile.txt";
4

9 回答 9

19

遇到了同样的问题,找到了另一种解决问题的方法:

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; 

    }
于 2011-09-13T10:28:31.183 回答
14

MSDN似乎建议您的路径被认为是相对的,因此它会尝试使用提供的凭据登录到 FTP 服务器,然后将当前目录设置为该<UserLoginDirectory>/path目录。如果这与您的文件所在的目录不同,您将收到 550 错误。

于 2011-02-01T16:19:39.193 回答
3

在以下代码示例中,我尝试使用以下数据并且它有效。

FTP 登录位置是C:\FTP.

文件原始位置C:\FTP\Data\FTP.txt

要移动的文件,C:\FTP\Move\FTP.txt.

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();
于 2016-03-03T07:34:35.357 回答
1

我能够让这个工作,但只能通过使用服务器上存在的路径,即/DRIVELETTER:/FOLDERNAME/filename在 RenameTo = "

于 2011-04-11T16:47:47.203 回答
1

如果你只有绝对路径怎么办?

好的,我遇到了这篇文章,因为我遇到了同样的错误。答案似乎是使用相对路径,这不能很好地解决我的问题,因为我将文件夹路径作为绝对路径字符串。

我想出的解决方案是即时工作的,但至少可以说是丑陋的。我会将其作为社区 wiki 答案,如果有人有更好的解决方案,请随时编辑。

自从我了解到这一点后,我有 2 个解决方案。

  1. 从移动到路径中获取绝对路径,并将其转换为相对 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();
    }
    

或者...

  1. 从“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;
    }
    
于 2011-08-19T00:51:22.797 回答
0

您是否在 FTP 服务中定义了这些文件夹?FTP 服务是否正在运行?如果任一问题的答案是否定的,则不能使用 FTP 移动文件。

尝试在 FTP 客户端中打开 FTP 文件夹,看看会发生什么。如果您仍然有错误,则说明您的定义有问题,因为 FTP 服务看不到该文件夹​​,或者该文件夹在逻辑上不在您认为它在 FTP 服务中的位置。

您还可以打开 IIS 管理器并查看 FTP 中的设置。

至于其他移动文件的方法,您可以轻松地从 UNC 路径移动到另一个路径,只要运行程序的帐户对两者都具有适当的权限。UNC 路径类似于 HTTP 或 FTP 路径,方向相反,没有指定协议。

于 2011-02-01T16:15:03.990 回答
0

代码看起来正确。所以要么你有错误的路径,文件不存在,要么你需要尊重大小写(显然 Windows 不区分大小写,但 Linux、Unix 是)。

您是否尝试在浏览器中打开文件?打开 Windows 文件资源管理器并在路径栏中键入地址,看看你得到了什么。

于 2011-02-01T16:19:47.480 回答
-1

你可以使用这个代码:

文件原始位置“ ftp://example.com/directory1/Somefile.file ”。

要移动的文件,“/newDirectory/Somefile.file”。

请注意,目标 URL 不需要以: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;
于 2018-09-04T11:18:02.163 回答
-2

我正在处理相同类型的项目,尝试构建一个可以移动文件并在文件所在的服务器上运行的 Web 服务。使用参数构建它以传入文件名。在写入文件开始时,您可能希望在文件名中附加一个值,例如与文件相关的数据的 PK 等。

于 2012-02-07T19:46:20.870 回答