2012-02-08 156 views
2

我們正試圖將文件移動到FTP站點。我們需要創建一個文件夾結構是這樣的:FTP:自動創建嵌套目錄

/deeply/nested/folder/structure/index.html

昨天,我們意識到我們不能一次創建多個文件夾,所以這不起作用:

MKD /深/嵌套/文件夾/結構

所以,在代碼中,我們寫了創建的每個文件夾循環,一個一次忽略由已存在的文件夾引起的錯誤。忽略錯誤是嚴重的。

是一種在一個動作中創建這些嵌套文件夾的方法,而不是多個?是否有命令查看文件夾是否已經存在?如果我們只是將文件推出(包括完整路徑),FTP能夠足夠聰明地爲我創建目錄嗎?

回答

2

不,沒有標準的方法來創建子文件夾的文件夾。也沒有標準的方法來檢查目錄是否存在。您需要使用LIST或MLSD(在支持的情況下)並解析結果。你不能只使用一些支持所需功能的第三方組件嗎?

+0

LIST和NLST可能會導致超時而不會導致立即失敗。只要目錄實際存在,它們就能正常工作。 – 2012-02-08 20:05:05

+0

問題的一部分是我們正在接收來自客戶的FTP信息。我們不知道他們使用的FTP服務器。就我個人而言,我認爲我們正在解決錯誤的問題,並且一般來說需要考慮FTP的替代方案。但是,這是一個相當標準(如果不是很差)的方法來跨站點加載HTML頁面。像S3這樣的事情可能不是一種選擇。 – 2012-02-08 20:07:29

+0

@TravisParks寫得不好的服務器會導致任何事情。命令本身不會導致任何事情。至於替代方案,請看看SFTP(SSH文件傳輸協議)。 – 2012-02-09 06:04:54

0

我在這裏寫了一個簡單的C#示例,也許有人會需要此代碼。

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Net; 

namespace Deployer 
{ 
    public class RecursiveFolderUploader 
    { 
     private const string SrcFullPath = @"C:\prg\Snowinmars\Snowinmars.Ui"; 
     private readonly IList<string> foldersOnServer; 
     private Client ftpClient; // that's your ftp client, init it 

     public RecursiveFolderUploader() 
     { 
      this.foldersOnServer = new List<string>(); 
     } 

     private void UploadAll(DirectoryInfo directoryInfo) 
     { 
      // ftp://login:[email protected]/path/to/root/mydir/anotherdir/file.dat 
      // ^________________uri_______________________^_relevationPath_^ 
      foreach (var file in directoryInfo.EnumerateFiles()) 
      { 
       if (!file.Directory.FullName.StartsWith(RecursiveFolderUploader.SrcFullPath)) 
       { 
        throw new InvalidOperationException($"File {file.FullName} is not from {RecursiveFolderUploader.SrcFullPath} folder"); 
       } 

       string relevationPath; // all folders from root up to file 

       if (file.Directory.FullName.Length == RecursiveFolderUploader.SrcFullPath.Length) 
       { 
        relevationPath = ""; 
       } 
       else 
       { 
        relevationPath = file.Directory.FullName.Substring(RecursiveFolderUploader.SrcFullPath.Length, file.Directory.FullName.Length - RecursiveFolderUploader.SrcFullPath.Length); 

        if (relevationPath.StartsWith("\\")) 
        { 
         relevationPath = relevationPath.Remove(0, 1); 
        } 
       } 

       string destination; 
       if (string.IsNullOrWhiteSpace(relevationPath)) 
       { 
        destination = file.Name; 
       } 
       else 
       { 
        destination = Path.Combine(relevationPath, file.Name).Replace("\\", "/"); 
       } 

       try 
       { 
        ftpClient.UploadFile(file.FullName, destination); 
       } 
       catch (WebException e) 
       { 
        // that means that there's no such folder or something else goes wrong 
        // we can check it by creating folders and try again 
        var parts = relevationPath.Replace("\\", "/").Split('/'); 

        for (int i = 1; i <= parts.Length; i++) 
        { 
         var path = string.Join("/", parts.Take(i)); 

         if (!foldersOnServer.Contains(path)) 
         { 
          ftpClient.MakeDirectory(path); 
          foldersOnServer.Add(path); 
         } 
        } 

        try 
        { 
         ftpClient.UploadFile(file.FullName, destination); 
        } 
        catch (Exception innerE) 
        { 
         // if it doesn't help - trouble isn't in folders 
         throw new WebException($"Can't find folder {relevationPath}", innerE); 
        } 
       } 
      } 

      foreach (var directory in directoryInfo.EnumerateDirectories()) 
      { 
       UploadAll(directory); 
      } 
     } 
    } 
}