2014-09-12 11 views
5

tworzę aplikację, która będzieSSH.NET przesłać kilka plików asynchronicznie zgłasza wyjątek

  1. proces plik CSV,
  2. tworzenia JObject dla każdego rekordu w CSV pliku i zapisać jako plik txt JSON, i wreszcie
  3. przesłać wszystkie te pliki JSON do SFTP serwerze

Po rozglądać się za wolna biblioteka dla trzeciego punktu, postanowiłem użyć SSH.NET.

Utworzono następującą klasę, aby wykonać operację przesyłania asynchronicznie.

public class JsonFtpClient : IJsonFtpClient 
{ 
    private string _sfptServerIp, _sfptUsername, _sfptPassword; 

    public JsonFtpClient(string sfptServerIp, string sfptUsername, string sfptPassword) 
    { 
     _sfptServerIp = sfptServerIp; 
     _sfptUsername = sfptUsername; 
     _sfptPassword = sfptPassword; 
    } 

    public Task<string> UploadDocumentAsync(string sourceFilePath, string destinationFilePath) 
    { 
     return Task.Run(() => 
     { 
      using (var client = new SftpClient(_sfptServerIp, _sfptUsername, _sfptPassword)) 
      { 
       client.Connect(); 

       using (Stream stream = File.OpenRead(sourceFilePath)) 
       { 
        client.UploadFile(stream, destinationFilePath); 
       } 

       client.Disconnect(); 
      } 
      return (destinationFilePath); 
     }); 
    } 
} 

Sposób UploadDocumentAsync zwraca TPL Task tak, że mogę nazwać to, aby przesłać kilka plików asynchronicznie.

Ja nazywam to UploadDocumentAsync metodę z następującą metodą, która jest w innej klasie:

private async Task<int> ProcessJsonObjects(List<JObject> jsons) 
{ 
    var uploadTasks = new List<Task>(); 
    foreach (JObject jsonObj in jsons) 
    { 
     var fileName = string.Format("{0}{1}", Guid.NewGuid(), ".txt"); 

     //save the file to a temp location 
     FileHelper.SaveTextIntoFile(AppSettings.ProcessedJsonMainFolder, fileName, jsonObj.ToString()); 

     //call the FTP client class and store the Task in a collection 
     var uploadTask = _ftpClient.UploadDocumentAsync(
       Path.Combine(AppSettings.ProcessedJsonMainFolder, fileName), 
       string.Format("/Files/{0}", fileName)); 

     uploadTasks.Add(uploadTask); 
    } 

    //wait for all files to be uploaded 
    await Task.WhenAll(uploadTasks); 

    return jsons.Count(); 
} 

Chociaż wyniki pliku CSV tysięcy rekordów JSON, ale chcę, aby przesłać je w partiach co najmniej 50 Ten ProcessJsonObjects zawsze otrzymuje listę 50 JObject s w czasie, który chcę przesłać asynchronicznie do serwera SFTP. Ale pojawia się następujący błąd na client.Connect(); linii metody UploadDocumentAsync:

Session operation has timed out 

zmniejszenie wielkości wsadu do 2 działa dobrze, ale czasami powoduje następujący błąd:

Client not connected. 

muszę być w stanie przesyłaj wiele plików w tym samym czasie. Lub powiedz mi, czy serwer IIS lub SFTP wymaga konfiguracji dla tego typu operacji i co to jest.

Co robię źle? Twoja pomoc jest bardzo ceniona.

+0

Wydaje mi się dość prawdopodobne, że host FTP ogranicza się do 2 jednoczesnych połączeń na kliencie, jeśli można go uruchomić, gdy zmniejszy się do 2 klientów naraz. –

+0

tak .. to jest to, co myślałem wcześniej. ale to czasami nie działa, nawet w przypadku równoczesnego ładowania dwóch plików i generowania drugiego błędu. – Aamir

+0

Host FTP ogranicza Cię, a czasami, gdy twój host jest zbyt zajęty (obsługując innych klientów), może nie odpowiadać. Przesyłanie 50 plików to zła logika, najlepiej, jeśli wszystkie pliki są spakowane w jednym pliku, a jeden plik powinien zostać przesłany, a wiele 50 żądań jest marnowaniem zasobów sieciowych. –

Odpowiedz

2

Wzór jest całkowicie spasowany.

Nie czekasz w odpowiednich miejscach i nie łączysz się w odpowiednich miejscach, które powinny być przed wysłaniem, aby zmniejszyć opóźnienie.

Niepołączony błąd wynika z tego, że połączenie zostało zakończone przed nawiązaniem połączenia.

Przerywa większe, ponieważ nie wysyła się niczego zbyt długo.

+0

Dzięki @Jay. Czy możesz spróbować poprowadzić mnie przez jakiś kod? Nie rozumiem, co miałeś na myśli. Możesz mi pokazać, modyfikując napisany przeze mnie kod. – Aamir

+0

Zrób połączenia przed połączeniem. Wykonaj pojedyncze przesłanie. Gotowe. – Jay

+0

Mogliście napisać kod C# lub wkleić/zmodyfikować moje, aby być bardziej szczegółowym. – Aamir

Powiązane problemy