2016-05-04 11 views
12

के माध्यम से सभी फाइलें और उप-निर्देशिकाएं डाउनलोड करें सामान्य जानकारी
मैं अभी भी सी # सीखने की प्रक्रिया में हूं। मेरी मदद करने के लिए, मैं एक ऐसा प्रोग्राम बनाने की कोशिश कर रहा हूं जो मेरे सभी स्थानीय प्रोजेक्ट को स्वचालित रूप से मेरे एफ़टीपी सर्वर पर एक फ़ोल्डर के साथ सिंक्रनाइज़ कर देगा। ऐसा इसलिए है कि मैं स्कूल या घर पर हूं, मेरे पास हमेशा एक ही परियोजनाएं उपलब्ध हैं।सी # एफ़टीपी

मुझे पता है कि ड्रॉपबॉक्स जैसे प्रोग्राम हैं जो पहले से ही मेरे लिए ऐसा करते हैं, लेकिन मुझे लगता है कि ऐसा कुछ बनाने के लिए मुझे रास्ते में बहुत कुछ सिखाया जाएगा।

समस्या
मेरा लक्ष्य की दिशा में मेरा पहला कदम बस मेरी FTP सर्वर से सभी फाइलों को, उपनिर्देशिकाएं और subfiles डाउनलोड करने के लिए किया गया था। मैंने नीचे दिए गए कोड के साथ निर्देशिका से सभी फाइलें डाउनलोड करने में कामयाब रहे हैं। हालांकि, मेरा कोड केवल मुख्य नाम में फ़ोल्डर नाम और फ़ाइलों को सूचीबद्ध करता है। Subfolders और subfiles कभी वापस नहीं आते हैं और कभी डाउनलोड नहीं किया जाता है। इसके अलावा, सर्वर 550 त्रुटि देता है क्योंकि मैं फ़ोल्डरों को डाउनलोड करने की कोशिश कर रहा हूं जैसे कि वे फ़ाइलें हैं। मैं इस पर 4+ घंटों के लिए रहा हूं, लेकिन मुझे इन समस्याओं को ठीक करने और इसे काम करने के तरीके पर कुछ भी नहीं मिला है। वजह मैं तुम लोगों ने मुझे बाहर करने में मदद करेगा :)

कोड आशा करती हूं कि

public string[] GetFileList() 
{ 
    string[] downloadFiles; 
    StringBuilder result = new StringBuilder(); 
    WebResponse response = null; 
    StreamReader reader = null; 

    try 
    { 
     FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url); 
     request.UseBinary = true; 
     request.Method = WebRequestMethods.Ftp.ListDirectory; 
     request.Credentials = new NetworkCredential(ftpUserName, ftpPassWord); 
     request.KeepAlive = false; 
     request.UsePassive = false; 
     response = request.GetResponse(); 
     reader = new StreamReader(response.GetResponseStream()); 
     string line = reader.ReadLine(); 
     while (line != null) 
     { 
      result.Append(line); 
      result.Append("\n"); 
      line = reader.ReadLine(); 
     } 
     result.Remove(result.ToString().LastIndexOf('\n'), 1); 
     return result.ToString().Split('\n'); 
    } 
    catch (Exception ex) 
    { 
     if (reader != null) 
     { 
      reader.Close(); 
     } 
     if (response != null) 
     { 
      response.Close(); 
     } 
     downloadFiles = null; 
     return downloadFiles; 
    } 
} 

private void Download(string file) 
{ 
    try 
    { 
     string uri = url + "/" + file; 
     Uri serverUri = new Uri(uri); 
     if (serverUri.Scheme != Uri.UriSchemeFtp) 
     { 
      return; 
     } 
     FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url + "/" + file); 
     request.UseBinary = true; 
     request.Method = WebRequestMethods.Ftp.DownloadFile; 
     request.Credentials = new NetworkCredential(ftpUserName, ftpPassWord); 
     request.KeepAlive = false; 
     request.UsePassive = false; 
     FtpWebResponse response = (FtpWebResponse)request.GetResponse(); 
     Stream responseStream = response.GetResponseStream(); 
     FileStream writeStream = new FileStream(localDestnDir + "\\" + file, FileMode.Create);     
     int Length = 2048; 
     Byte[] buffer = new Byte[Length]; 
     int bytesRead = responseStream.Read(buffer, 0, Length); 
     while (bytesRead > 0) 
     { 
      writeStream.Write(buffer, 0, bytesRead); 
      bytesRead = responseStream.Read(buffer, 0, Length); 
     } 
     writeStream.Close(); 
     response.Close(); 
    } 
    catch (WebException wEx) 
    { 
     MessageBox.Show(wEx.Message, "Download Error"); 
    } 
    catch (Exception ex) 
    { 
     MessageBox.Show(ex.Message, "Download Error"); 
    } 
} 

उत्तर

19

FtpWebRequest (डाउनलोड सहित) पुनरावर्ती फ़ाइल के संचालन के लिए किसी भी स्पष्ट समर्थन नहीं है।

  • सूची दूरस्थ निर्देशिका
  • दोहराएं प्रविष्टियों, फ़ाइलों को डाउनलोड और निदेशिकाओं में recursing (उन्हें फिर से लिस्टिंग, आदि)

ट्रिकी भाग की पहचान है: आप प्रत्यावर्तन खुद को लागू करना उपनिर्देशिका से फ़ाइलें। FtpWebRequest के साथ पोर्टेबल तरीके से ऐसा करने का कोई तरीका नहीं है। दुर्भाग्यवश FtpWebRequestMLSD कमांड का समर्थन नहीं करता है, जो FTP प्रोटोकॉल में फ़ाइल विशेषताओं के साथ निर्देशिका सूची पुनर्प्राप्त करने का एकमात्र पोर्टेबल तरीका है। Checking if object on FTP server is file or directory भी देखें।

आपके विकल्प हैं:

  • एक फ़ाइल नाम उस फ़ाइल के लिए असफल होना निश्चित है और निर्देशिका (या इसके विपरीत) के लिए सफल होता है पर एक संचालन करते हैं। अर्थात। आप "नाम" डाउनलोड करने का प्रयास कर सकते हैं। यदि यह सफल होता है, तो यह एक फ़ाइल है, अगर यह विफल हो जाती है, तो यह एक निर्देशिका है।
  • आप भाग्यशाली हो सकता है और अपने विशिष्ट मामले में, आप (यानी अपनी सभी फ़ाइलों को एक विस्तार है, जबकि उप निर्देशिकाओं नहीं करते हैं)
  • आप एक लंबी निर्देशिका लिस्टिंग का उपयोग एक फ़ाइल नाम से एक निर्देशिका से एक फ़ाइल बता सकते हैं (LIST आदेश = ListDirectoryDetails विधि) और सर्वर-विशिष्ट सूची को पार्स करने का प्रयास करें। कई एफ़टीपी सर्वर * निक्स-शैली सूची का उपयोग करते हैं, जहां आप प्रविष्टि की शुरुआत में d द्वारा निर्देशिका की पहचान करते हैं। लेकिन कई सर्वर एक अलग प्रारूप का उपयोग करते हैं।निम्न उदाहरण इस दृष्टिकोण (* nix प्रारूप मानते हुए)
void DownloadFtpDirectory(string url, NetworkCredential credentials, string localPath) 
{ 
    FtpWebRequest listRequest = (FtpWebRequest)WebRequest.Create(url); 
    listRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails; 
    listRequest.Credentials = credentials; 

    List<string> lines = new List<string>(); 

    using (FtpWebResponse listResponse = (FtpWebResponse)listRequest.GetResponse()) 
    using (Stream listStream = listResponse.GetResponseStream()) 
    using (StreamReader listReader = new StreamReader(listStream)) 
    { 
     while (!listReader.EndOfStream) 
     { 
      lines.Add(listReader.ReadLine()); 
     } 
    } 

    foreach (string line in lines) 
    { 
     string[] tokens = 
      line.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries); 
     string name = tokens[8]; 
     string permissions = tokens[0]; 

     string localFilePath = Path.Combine(localPath, name); 
     string fileUrl = url + name; 

     if (permissions[0] == 'd') 
     { 
      if (!Directory.Exists(localFilePath)) 
      { 
       Directory.CreateDirectory(localFilePath); 
      } 

      DownloadFtpDirectory(fileUrl + "/", credentials, localFilePath); 
     } 
     else 
     { 
      FtpWebRequest downloadRequest = (FtpWebRequest)WebRequest.Create(fileUrl); 
      downloadRequest.Method = WebRequestMethods.Ftp.DownloadFile; 
      downloadRequest.Credentials = credentials; 

      using (FtpWebResponse downloadResponse = 
         (FtpWebResponse)downloadRequest.GetResponse()) 
      using (Stream sourceStream = downloadResponse.GetResponseStream()) 
      using (Stream targetStream = File.Create(localFilePath)) 
      { 
       byte[] buffer = new byte[10240]; 
       int read; 
       while ((read = sourceStream.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        targetStream.Write(buffer, 0, read); 
       } 
      } 
     } 
    } 
} 

उपयोग समारोह की तरह उपयोग करता है:

NetworkCredential credentials = new NetworkCredential("user", "mypassword"); 
string url = "ftp://ftp.example.com/directory/to/download/"; 
DownloadFtpDirectory(url, credentials, @"C:\target\directory"); 

आप सर्वर को पार्स साथ मुसीबतों से बचना चाहते हैं विशिष्ट निर्देशिका सूची स्वरूप, एक तृतीय पक्ष लाइब्रेरी का उपयोग करें जो MLSD कमांड का समर्थन करता है और/या विभिन्न LIST लिस्टिंग प्रारूपों का विश्लेषण करता है; और रिकर्सिव डाउनलोड।

WinSCP .NET assembly साथ उदाहरण के लिए आप Session.GetFiles लिए एक कॉल के साथ पूरी निर्देशिका डाउनलोड कर सकते हैं:

// Setup session options 
SessionOptions sessionOptions = new SessionOptions 
{ 
    Protocol = Protocol.Ftp, 
    HostName = "ftp.example.com", 
    UserName = "user", 
    Password = "mypassword", 
}; 

using (Session session = new Session()) 
{ 
    // Connect 
    session.Open(sessionOptions); 

    // Download files 
    session.GetFiles("/directory/to/download/*", @"C:\target\directory\*").Check(); 
} 

आंतरिक रूप से, WinSCP, MLSD आदेश का उपयोग करता है, तो सर्वर द्वारा समर्थित। यदि नहीं, तो यह LIST कमांड का उपयोग करता है और विभिन्न लिस्टिंग प्रारूपों के दर्जनों का समर्थन करता है।

Session.GetFiles method डिफ़ॉल्ट रूप से रिकर्सिव है।

(मैं WinSCP के लेखक हूँ)

+2

मैं स्वीकार किए जाते हैं जवाब देने के लिए अपने जवाब बदल दिया है के रूप में मैं यह से बहुत कुछ सीखा है और सभी efford के लिए आप इसे में डाल दिया गया है! एक बार फिर धन्यवाद! – icecub

+0

हाय वहाँ मैं आपकी लाइब्रेरी का उपयोग करने की कोशिश कर रहा हूं लेकिन मुझे अपने कनेक्शन पर एसएसएल/टीएलएस की आवश्यकता है, मैं इसे सक्षम FTPsquest के माध्यम से सक्षम कर रहा हूं EnableSsl = true का उपयोग करके यह आपके सत्र विकल्पों में सेट किया जा सकता है? – Jay

+0

मैं इसे क्रमशः निष्क्रिय और स्पष्ट करने के लिए FtpMode और FTPSecure को सेट करके कनेक्ट करने में सक्षम था, महान लाइब्रेरी रिकर्सिव फीचर उत्कृष्ट है, एक सवाल यह है कि एक ऐसी सुविधा है जो फाइलों को पकड़ लेती है जो नए फ़ोल्डर में मौजूद नहीं है, इसलिए अनिवार्य रूप से केवल नए हथियार फाइलें जिन्हें पहले ही कॉपी किया गया है – Jay

संबंधित मुद्दे