簡體   English   中英

如何使用 FTP 在目錄之間移動文件?

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

我有一個程序需要在 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)。

是否應該可以在這樣的目錄之間移動文件,如果不能,怎么可能?

為了解決提出的一些觀點/建議:

  1. 我可以從源目錄下載相同的文件,所以它肯定存在(我正在做的是先下載文件,然后將它移到其他地方)。
  2. 我可以從瀏覽器(源目錄和目標目錄)訪問 ftp 站點
  3. ftp 服務器在我本地機器上我自己的 IIS 實例下運行。
  4. 路徑和大小寫正確,沒有特殊字符。

此外,我嘗試將目錄路徑設置為:

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

源路徑和目標路徑都適用 - 但這也沒有區別。

我找到了這篇文章,它似乎說將目標指定為相對路徑會有所幫助 - 似乎不可能將絕對路徑指定為目標。

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

遇到了同樣的問題,找到了另一種解決問題的方法:

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似乎暗示您的路徑被視為相對路徑,因此它嘗試使用提供的憑據登錄到 FTP 服務器,然后將當前目錄設置為<UserLoginDirectory>/path目錄。 如果這不是您的文件所在的目錄,您將收到 550 錯誤。

在下面的代碼示例中,我嘗試使用以下數據並且它有效。

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();

我能夠讓它工作,但只能通過使用服務器上存在的路徑,即/DRIVELETTER:/FOLDERNAME/filename in RenameTo = "

如果你只有絕對路徑怎么辦?

好的,我遇到了這篇文章,因為我遇到了同樣的錯誤。 答案似乎是使用相對路徑,這對於解決我的問題不是很好,因為我將文件夾路徑作為絕對路徑字符串。

我即時提出的解決方案有效,但至少可以說是丑陋的。 我會將其作為社區 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; }

您是否在 FTP 服務中定義了這些文件夾? FTP 服務是否正在運行? 如果任一問題的答案是否定的,則不能使用 FTP 移動文件。

嘗試在 FTP 客戶端中打開 FTP 文件夾,看看會發生什么。 如果您仍然有錯誤,則您的定義有問題,因為 FTP 服務沒有看到該文件夾​​,或者該文件夾在邏輯上不在您認為它在 FTP 服務中的位置。

您還可以打開 IIS 管理器並查看 FTP 中的設置。

至於移動文件的其他方法,您可以輕松地從一個 UNC 路徑移動到另一個路徑,只要運行程序的帳戶對這兩個路徑都具有適當的權限。 UNC 路徑類似於 HTTP 或 FTP 路徑,但方向相反且未指定協議。

代碼看起來是正確的。 所以要么你路徑錯誤,文件不存在,要么你需要尊重大小寫(顯然 Windows 不區分大小寫,但 Linux、Unix 是)。

您是否嘗試在瀏覽器中打開該文件? 打開 Windows 文件資源管理器並在路徑欄中鍵入地址,看看你得到了什么。

你可以使用這個代碼:

文件原始位置“ 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;

我正在處理相同類型的項目,嘗試構建一個可以移動文件並在文件所在的服務器上運行的 Web 服務。 使用參數構建它以傳入文件名。 在開始寫入文件時,您可能希望在文件名后附加一個值,例如與文件相關的數據的 PK 等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM