2011-02-01 190 views
16

我有一個程序需要將文件從FTP服務器上的一個目錄移動到另一個目錄。例如,該文件是:如何使用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(); 

但是這似乎並沒有工作 - 我得到以下錯誤:

The remote server returned an error: (550) File unavailable (e.g., file not found, no access).

起初我以爲這可能與權限有關,但據我所見,我有權訪問整個FTP站點(它位於本地PC上,uri已解析爲本地主機)。

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

解決一些已經提出的問題/建議:

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

此外,我已經嘗試設置目錄路徑是:

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

兩個源和目標路徑 - 但是這並沒有區別兩種。

我發現this文章,似乎說,指定目的地作爲相對路徑會有所幫助 - 它似乎不可能指定絕對路徑作爲目的地。

reqFTP.RenameTo = 「../Dir2/MyFile.txt"; 
+1

如果您將ftp://1.1.1.1/MAIN/Dir1/MyFile.txt插入到瀏覽器中,它是否正常工作? – 2011-02-01 16:12:19

+0

該路徑是否包含需要轉義的特殊字符? – 2011-02-01 16:18:11

+0

查看最新編輯內容,但答案是:是 - 它可以在瀏覽器中正常工作,否 - 路徑中沒有特殊字符 – 2011-02-02 07:45:15

回答

10

MSDN似乎表明,你的路徑被認爲是相對的,因此它會嘗試使用所提供的憑證登錄到FTP服務器,然後將當前目錄設置到<UserLoginDirectory>/path目錄。如果這不是你的文件所在的目錄,那麼你會得到一個550錯誤。

+0

查看最新編輯。我嘗試過%2f在路徑中的各種組合,但沒有成功 – 2011-02-02 10:03:09

0

您是否有FTP服務中定義的文件夾? FTP服務正在運行?如果兩個問題的答案都是否定的,則不能使用FTP來移動文件。

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

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

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

0

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

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

1

我能得到這個工作,但只有在RenameTo因爲它存在使用路徑在服務器上,即/DRIVELETTER:/FOLDERNAME/filename =「

1

如果你只有絕對路徑?

好吧,我來了因爲我得到了同樣的錯誤,答案似乎是使用相對路徑,這對於我的問題來說並不是很好,因爲我得到的文件夾路徑是絕對路徑字符串。解決方案我在飛行工作中遇到了難題,但至少可以說這是一個社區維基答案,如果有的話ne有更好的解決方案,隨時編輯這個。

由於我學到了這個,我有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」 下載文件,上傳到 「ftp到」 路徑,並從 「從FTP」 刪除路徑。

    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; 
    } 
    
16

有同樣的問題,發現另一種方式來解決這個問題:

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; 

    } 
-2

我上同一類型的項目工作,嘗試建立一個Web服務,可以移動的文件並在您的文件所在的服務器上運行。使用參數構建它以傳入文件名。當寫入開始你可能要追加價值的文件名的文件,說相關的文件等

1

在下面的代碼示例中,我試着用以下數據和它的工作數據的PK。

FTP登錄位置是 「C:\ FTP」。

文件原來的位置 「C:\ FTP \ DATA \ FTP.txt」。

文件被移動, 「C:\ FTP \移動\ 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();