2016-02-22 3 views
5

से बाहर जाने से पहले नींद डालता हूं, मैं एक परीक्षण FTP साइट पर फ़ाइल अपलोड करने के लिए System.Net.FtpClient असेंबली का उपयोग कर रहा हूं। जब तक मैं नीचे के अनुसार एक Thread.Sleep का उपयोग करें (जो मैं उपयोग करने के लिए नहीं करना चाहते हैं) जब मैं नीचे दिए गए कोड को चलाने फ़ाइल दूरस्थ स्थान में प्रकट नहीं होता:System.Net.FtpClient openwrite फ़ाइल अपलोड नहीं करता है जब तक कि मैं

using System; 
using System.IO; 
using System.Net; 
using System.Net.FtpClient; 
using System.Security.Cryptography.X509Certificates; 
using System.Threading; 

namespace FtpsUploadTest 
{ 
    /// <summary> 
    /// The ftp publisher. 
    /// </summary> 
    public class FtpPublisher 
    { 
     private readonly FtpsSettings _settings; 
     private readonly IFtpClient _ftpClient; 

     /// <summary> 
     /// Initializes a new instance of the <see cref="FtpPublisher"/> class. 
     /// </summary> 
     public FtpPublisher() 
     { 
      _ftpClient = new FtpClient(); 
      _settings = SettingsReader.GetMySettings(); 
      Init(); 
     } 


     /// <summary> 
     /// The publish. 
     /// </summary> 
     /// <param name="fileToUpload"> 
     /// The input file path. 
     /// </param> 
     public void Publish(string fileToUpload) 
     { 
      var remoteFileName = Path.GetFileName(fileToUpload); 

      Console.WriteLine("FTPS host: {0} remote path: {1}", _settings.FtpsRemoteHost, _settings.FtpsRemotePath); 

      if (!_ftpClient.IsConnected) 
      { 
       _ftpClient.Connect(); 
      } 

      var fullRemotePath = string.Format("{0}/{1}", _settings.FtpsRemotePath, remoteFileName); 

      using (var ftpStream = _ftpClient.OpenWrite(fullRemotePath)) 
      using (var inputStream = new FileStream(fileToUpload, FileMode.Open)) 
      { 
       inputStream.CopyTo(ftpStream); 
       Thread.Sleep(5000); // <------------------- DOESNT WORK IF REMOVE THIS SLEEP!! 
      } 

      Console.WriteLine("File '{0}' published successfully", fileToUpload); 
     } 


     private void Init() 
     { 
      _ftpClient.Host = _settings.FtpsRemoteHost; 
      _ftpClient.Port = _settings.FtpsRemotePort; 
      _ftpClient.DataConnectionConnectTimeout = 60000; 
      _ftpClient.ConnectTimeout = 60000; 
      _ftpClient.Credentials = new NetworkCredential(_settings.FtpsUserId, string.Empty); 
      _ftpClient.DataConnectionType = 0; 

      if (string.IsNullOrEmpty(_settings.CertFile) || string.IsNullOrEmpty(_settings.CertPassword)) 
      { 
       return; 
      } 

      _ftpClient.ClientCertificates.Add(CreateCertificate(_settings.CertFile, _settings.CertPassword)); 
      _ftpClient.EncryptionMode = (FtpEncryptionMode)2; 
      _ftpClient.DataConnectionEncryption = true; 
     } 


     private X509Certificate CreateCertificate(string certFile, string certPassword) 
     { 
      return new X509Certificate(certFile, certPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); 
     } 
    } 
} 

किसी को भी पता है कि मैं कैसे प्राप्त कर सकते हैं यह थ्रेड का उपयोग किए बिना काम करने के लिए। सो जाओ? मैंने flushing, धाराओं को बंद करने की कोशिश की है, लेकिन यह मदद नहीं करता है।

+0

आप अपने आवेदन में सूत्रण उपयोग करते हैं? क्या एक ही 'FtpPublisher' उदाहरण गलती से कई धागे द्वारा उपयोग किया जा सकता है? –

+0

क्या फ़ाइल सिर्फ कोड के लिए दृश्यमान नहीं है, भले ही आप डीबगर में कई सेकंड प्रतीक्षा करें? –

+0

जोआचिम, यहां कोई थ्रेडिंग नहीं किया जा रहा है। मैंने उदाहरण को यथासंभव सरल बना दिया है और समस्या को पुन: पेश करने में सक्षम था। – user1229458

उत्तर

3

दूरस्थ FTP सर्वर आपके कोड से पूरी तरह से असीमित रूप से कार्य कर रहा है। सर्वर की कॉन्फ़िगरेशन के आधार पर यह फ़ाइल उपलब्ध कराने से पहले वायरस या अन्य बहीखाता के लिए स्कैन जैसी चीजें कर सकता है। इसके बारे में आप कुछ भी नहीं कर सकते हैं जब तक कि आप FTP सर्वर पर प्रत्यक्ष नियंत्रण न रखें। इसके बावजूद इसे गहराई से कॉन्फ़िगरेशन में कुछ सुंदरता, या यहां तक ​​कि एक अलग सॉफ़्टवेयर पैकेज की आवश्यकता हो सकती है।

एक चीज जो आपके लिए काम कर सकती है वह अपलोड को पूरा करने के बाद फ़ाइल के लिए "मतदान" करना है। फ़ाइल के लिए जांचने वाला एक लूप बनाएं, 1 सेकंड प्रतीक्षा करता है, फिर फ़ाइल को तब तक दोहराता है जब तक वह फ़ाइल नहीं ढूंढता या छोड़ देता है। Async/Await पैटर्न, या एक अलग थ्रेड से कॉल-बैक, यदि आप कोई समस्या है तो इससे किसी भी UI फ्रीज से छुटकारा पाने में आपकी सहायता कर सकते हैं।

+0

धन्यवाद अगर मैं इसकी पुष्टि कर सकता हूं तो मुझे एफ़टीपी सर्वर के मालिक से जांच करने की आवश्यकता होगी। वे दावा करते हैं कि उनके पास अन्य क्लाइंट सफलतापूर्वक अपलोड हो रहे हैं, लेकिन यदि वे ग्राहक तुरंत बाहर नहीं निकलते हैं तो वे – user1229458

+1

समस्या को कभी नहीं देख पाएंगे, मुझे पता है कि यह एक पुराना धागा है, लेकिन इसके लायक होने के लिए ... क्या आपको कभी भी जवाब मिल गया था समाप्त? मैं एक ही मुद्दे पर चल रहा था और आपकी नींद विधि वास्तव में मदद की। मैंने अपने कार्यालय में एक लिनक्स बॉक्स पर एक क्रशएफटीपी सर्वर बनाया और समस्या (यह प्रतीत होता है) FTP सर्वर के साथ है। यदि आप डिस्क से लिखे जाने से पहले सर्वर से डिस्कनेक्ट करते हैं तो यह इसके बफर को फ्लश करता है। यह मेरे जैसा दिखता है। अगर आपको कुछ पता चला तो कृपया मुझे बताएं। –

1

ब्राडली जवाब देने के लिए धन्यवाद मैं एक समाधान में कामयाब रहे: FtpClient.OpenWrite (...) के साथ फ़ाइल अपलोड करने और उसके बाद मैं लगातार सर्वर है, जो कोड की समस्या को हल अपलोड प्रक्रिया के दौरान क्रियान्वित करने पर फ़ाइल आकार जाँच करें कि इसके बाद निष्पादित किया जाना चाहिए।

फिर मैं एक और समस्या में भाग गया जिसके लिए मैंने वर्कअराउंड प्रबंधित किया: दूरस्थ FTP सर्वर पर अपलोडिंग फ़ाइल के फ़ाइल आकार की जांच करते समय, आप हमेशा FtpClient.GetFileSize (...) के माध्यम से फ़ाइल का आकार नहीं प्राप्त कर सकते एफ़टीपी कमांड (SIZE) के कारण जो सभी एफ़टीपी सर्वरों द्वारा समर्थित नहीं है। समाधान निम्न था: यदि FtpClient.GetFileSize (...) रिटर्न -1 से अधिक है, तो SIZE कमांड काम करता है और इसका उपयोग किया जा सकता है। यदि फ़ंक्शन -1 लौटाता है, तो आप सर्वर पर निर्दिष्ट फ़ोल्डर में फ़ाइलों की एक सूची पर जा सकते हैं। वहां आपको FtpListItem की एक सरणी मिलती है जिसमें "आकार" नामक एक संपत्ति होती है। आकार वही मान देता है जैसे FtpClient.GetFileSize (...) वास्तव में चाहिए।

उदाहरण कोड:

const string folderPath = "/media/"; 
string fileName = "image.png"; 
string fullRemotePath = folderPath + fileName; 
string fileToUpload = @"C:\image.png"; 
FtpClient ftpClient = new FtpClient(); 
// start FtpClient connection etc 

FileInfo fileInfo = new FileInfo(fileToUpload); 
long actualFileSize = fileInfo.Length; 
using (var ftpStream = ftpClient.OpenWrite(fullRemotePath)) 
{ 
    using (var inputStream = new FileStream(fileToUpload, FileMode.Open)) 
    { 
     inputStream.CopyTo(ftpStream); 
     //Thread.Sleep(5000); <-- not necessary anymore 
    } 
} 
long fileSizeOnFtp = ftpClient.GetFileSize(fullRemotePath); 
while (fileSizeOnFtp < actualFileSize) 
{ 
    if (fileSizeOnFtp > -1) 
    { 
     fileSizeOnFtp = ftpClient.GetFileSize(fullRemotePath); 
    } 
    else 
    { 
     var ftpListItem = ftpClient.GetListing(folderPath).Where(x => x.Name == fileName).FirstOrDefault(); 
     if (ftpListItem != null) 
     { 
      fileSizeOnFtp = ftpListItem.Size; 
     } 
     else 
     { 
      // the program only could run into this issue if the folder couldn't be listed 
      throw new Exception(); 
     } 
    } 
} 
// execute everything else after ftp upload has finished 
संबंधित मुद्दे

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