简体   繁体   English

如何使用 FTP 在目录之间移动文件?

[英]How can I use FTP to move files between directories?

I have a program that needs to move a file from one directory to another on an FTP server.我有一个程序需要在 FTP 服务器上将文件从一个目录移动到另一个目录。 For example, the file is in:例如,文件位于:

ftp://1.1.1.1/MAIN/Dir1

and I need to move the file to:我需要将文件移动到:

ftp://1.1.1.1/MAIN/Dir2

I found a couple of articles recommending use of the Rename command, so I tried the following:我找到了几篇推荐使用 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();

But this doesn't seem to work – I get the following error:但这似乎不起作用 - 我收到以下错误:

The remote server returned an error: (550) File unavailable (eg, file not found, no access).远程服务器返回错误:(550) 文件不可用(例如,找不到文件,无法访问)。

At first I thought this might relate to permissions, but as far as I can see, I have permissions to the entire FTP site (it is on my local PC and the uri is resolved to localhost).起初我认为这可能与权限有关,但据我所知,我拥有整个 FTP 站点的权限(它在我的本地 PC 上,uri 解析为 localhost)。

Should it be possible to move files between directories like this, and if not, how is it possible?是否应该可以在这样的目录之间移动文件,如果不能,怎么可能?

To address some of the point / suggestions that have been raised:为了解决提出的一些观点/建议:

  1. I can download the same file from the source directory, so it definitely exists (what I'm doing is downloading the file first, and then moving it somewhere else).我可以从源目录下载相同的文件,所以它肯定存在(我正在做的是先下载文件,然后将它移到其他地方)。
  2. I can access the ftp site from a browser (both the source and target directory)我可以从浏览器(源目录和目标目录)访问 ftp 站点
  3. The ftp server is running under my own IIS instance on my local machine. ftp 服务器在我本地机器上我自己的 IIS 实例下运行。
  4. The path and case are correct and there are no special characters.路径和大小写正确,没有特殊字符。

Additionally, I have tried setting the directory path to be:此外,我尝试将目录路径设置为:

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

Both for the source and target path - but this makes no difference either.源路径和目标路径都适用 - 但这也没有区别。

I found this article, which seems to say that specifying the destination as a relative path would help - it doesn't appear to be possible to specify an absolute path as the destination.我找到了这篇文章,它似乎说将目标指定为相对路径会有所帮助 - 似乎不可能将绝对路径指定为目标。

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

Had the same problem and found another way to solve the problem:遇到了同样的问题,找到了另一种解决问题的方法:

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; 

    }

MSDN seems to suggest that your path is considered relative, and therefore it tries to log in to the FTP server using the supplied credentials, then sets the current directory to the <UserLoginDirectory>/path directory. MSDN似乎暗示您的路径被视为相对路径,因此它尝试使用提供的凭据登录到 FTP 服务器,然后将当前目录设置为<UserLoginDirectory>/path目录。 If this isn't the same directory where your file is, you'll get a 550 error.如果这不是您的文件所在的目录,您将收到 550 错误。

In the following code example I tried with the following data and it works.在下面的代码示例中,我尝试使用以下数据并且它有效。

FTP Login location is C:\\FTP . FTP 登录位置是C:\\FTP

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

File to be moved, C:\\FTP\\Move\\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();

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

What if you only have absolute paths?如果你只有绝对路径怎么办?

Ok, I came across this post because I was getting the same error.好的,我遇到了这篇文章,因为我遇到了同样的错误。 The answer seems to be to use a relative path, which is not very good as a solution to my issue, because I get the folder paths as absolute path strings.答案似乎是使用相对路径,这对于解决我的问题不是很好,因为我将文件夹路径作为绝对路径字符串。

The solutions I've come up with on the fly work but are ugly to say the least.我即时提出的解决方案有效,但至少可以说是丑陋的。 I'll make this a community wiki answer, and if anyone has a better solution, feel free to edit this.我会将其作为社区 wiki 答案,如果有人有更好的解决方案,请随时编辑。

Since I've learned this I have 2 solutions.自从我学到了这一点,我有 2 个解决方案。

  1. Take the absolute path from the move to path, and convert it to a relative URL.从移动到路径中获取绝对路径,并将其转换为相对 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(); }

or...要么...

  1. Download the file from the "ftp from" path, upload it to the "ftp to" path and delete it from the "ftp from" path.从“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; }

Do you have those folders defined in the FTP service?您是否在 FTP 服务中定义了这些文件夹? Is the FTP service running? FTP 服务是否正在运行? If the answer to either question is no, you cannot use FTP to move the files.如果任一问题的答案是否定的,则不能使用 FTP 移动文件。

Try opening the FTP folder in an FTP client and see what happens.尝试在 FTP 客户端中打开 FTP 文件夹,看看会发生什么。 If you still have an error, there is something wrong with your definition as the FTP service does not see the folder or the folder is not logically where you think it is in the FTP service.如果您仍然有错误,则您的定义有问题,因为 FTP 服务没有看到该文件夹​​,或者该文件夹在逻辑上不在您认为它在 FTP 服务中的位置。

You can also open up the IIS manager and look at how things are set up in FTP.您还可以打开 IIS 管理器并查看 FTP 中的设置。

As for other methods to move files, you can easily move from a UNC path to another, as long as the account the program runs under has proper permissions to both.至于移动文件的其他方法,您可以轻松地从一个 UNC 路径移动到另一个路径,只要运行程序的帐户对这两个路径都具有适当的权限。 The UNC path is similar to an HTTP or FTP path, with whacks in the opposite direction and no protocol specified. UNC 路径类似于 HTTP 或 FTP 路径,但方向相反且未指定协议。

The code looks correct.代码看起来是正确的。 So either you have the wrong path, the file DOESNT exist or you need to respect case (obviously Windows is not case sensitive, but Linux, Unix are).所以要么你路径错误,文件不存在,要么你需要尊重大小写(显然 Windows 不区分大小写,但 Linux、Unix 是)。

Did you try to open the file in a browser?您是否尝试在浏览器中打开该文件? Open Windows File Explorer and type the address in the path bar and see what you get.打开 Windows 文件资源管理器并在路径栏中键入地址,看看你得到了什么。

U can use this code:你可以使用这个代码:

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

File to be moved, "/newDirectory/Somefile.file".要移动的文件,“/newDirectory/Somefile.file”。

Note that destination Url not need start with: ftp://example.com请注意,目标网址不需要以: 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;

I am working on the identical type of project, try building a web service that can move the files around and runs on the server where your files are.我正在处理相同类型的项目,尝试构建一个可以移动文件并在文件所在的服务器上运行的 Web 服务。 Build it with a parameter to pass in the file name.使用参数构建它以传入文件名。 When writing the file to begin with you might want to append a value to the file name, say the PK of the data that correlates to the file etc.在开始写入文件时,您可能希望在文件名后附加一个值,例如与文件相关的数据的 PK 等。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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