2014-06-17 23 views
7

Mamy klienta .NET, który używa SignalR do wywołania metody Server, ale parametr wydaje się bardzo duży, na taki scenariusz, jak to naprawić?Jak wysłać duże dane za pośrednictwem SignalR w klientach .NET

kod klienta: Kod

public async Task FooAsync() 
{ 
    var hubConnection = new HubConnection(...); 
    await hubConnection.Start(); 

    var hubProxy = hubConnection.CreateHubProcx("ValueHub"); 
    //the content is very long, about 11776065 bytes (11MB) 
    var content = File.ReadAllText(...); 
    hubProxy.Invoke("Send", content); 
    ... 
} 

Serwer:

[HubName("ValueHub")] 
public class ValueHub : Hub 
{ 
    public void Send(string json) 
    { 

    } 
} 

ze stosu wyjątku i kodu źródłowego, znalazłem SignalR wewnętrznie używać HttpClient z FormUrlEncodedContent typu HttpContent, a może ograniczenie przyszedł stąd.

System.UriFormatException was unhandled 
    HResult=-2146233033 
    Message=Invalid URI: The Uri string is too long. 
    Source=System 
    StackTrace: 
     at System.UriHelper.EscapeString(String input, Int32 start, Int32 end, Char[] dest, Int32& destPos, Boolean isUriString, Char force1, Char force2, Char rsvd) 
     at System.Uri.EscapeDataString(String stringToEscape) 
     at System.Net.Http.FormUrlEncodedContent.Encode(String data) 
     at System.Net.Http.FormUrlEncodedContent.GetContentByteArray(IEnumerable`1 nameValueCollection) 
     at System.Net.Http.FormUrlEncodedContent..ctor(IEnumerable`1 nameValueCollection) 
     at Microsoft.AspNet.SignalR.Client.Http.DefaultHttpClient.Post(String url, Action`1 prepareRequest, IDictionary`2 postData, Boolean isLongRunning) 
     at Microsoft.AspNet.SignalR.Client.Transports.HttpBasedTransport.Send(IConnection connection, String data, String connectionData) 
     at Microsoft.AspNet.SignalR.Client.Transports.AutoTransport.Send(IConnection connection, String data, String connectionData) 
     at Microsoft.AspNet.SignalR.Client.Connection.Send(String data) 
     at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke[T](String method, Object[] args) 
     at Microsoft.AspNet.SignalR.Client.Hubs.HubProxy.Invoke(String method, Object[] args) 

Jakieś dobre sugestie dotyczące tego problemu?

+4

Szczerze mówiąc, nie zrobiłbym tego w hubie. Użyj koncentratora jako struktury przesyłania komunikatów, aby poinformować klienta o pojawieniu się nowych danych. Klient może następnie pobrać dane za pomocą api/webmethod lub innej techniki transportu. – Schadensbegrenzer

+0

To może Ci pomóc http://stackoverflow.com/questions/7043566/invalid-uri-ti--i-mising-is-too-long –

+0

Co to jest przypadek użycia? – Anders

Odpowiedz

6

Jak już się ustaliłeś - dane te są zbyt duże dla SIGNALR według własnego projektu.

Czy nie byłoby lepiej mieć inny proces, który robi to z normalnym API REST (GET/POST). Być może komunikat wskazujący użytkownikowi, że należy to zrobić, ponieważ czuje się bardzo "BATCH".

Po drugie, jeśli jest to wymaganie (możliwe nieprawidłowe narzędzie do pracy), rozważyć kompresję.

+0

Co z mniejszymi plikami? Chcę wysłać miniaturki 60 KB. Mogę powiedzieć mojemu serwerowi, aby zaakceptował tak długi ciąg zapytania (i tak będzie dość szybko), ale kodowanie URI SignalR nadal będzie blokować: S. –

1

jej łatwo to zrobić ..

  • dzielenia plików na kawałki bajt array (moich testów pokazuje max 10kB za kawałkiem wystarczy)
  • wysyłać kawałki do klienta z powołaniem się jak (i ​​obliczyć totalBytes dane kawałek masz):

    hubProxy.Invoke("Send", chunk,currentBytes,totalBytes); 
    
  • uzyskać kawałki z klientem i utworzyć tablicę bajtów i dołączyć każdy klocek, signalr wysyła pliki syncronously oznacza to dane będą odbierane jako send Kolejność
  • masz totalbytes i currentBytes dane, teraz wiesz, wszystkie otrzymane dane, należy zapisać ten bajt tablicy do pliku ze strumienia lub cokolwiek chcesz ..
+0

Będziesz musiał wysłać informacje o sekwencji wraz z nim, ponieważ czytam, że SignalR nie gwarantuje kolejności wiadomości. – TheLegendaryCopyCoder

9

Można dodać linię, która sprawia, że ​​rozmiar wiadomości ' nieskończona „w swoim Startup.cs ustawiając MaxIncomingWebSocketMessageSize null:

public class Startup 
    { 
     public void Configuration(IAppBuilder app) 
     { 
     app.MapSignalR(); 
     GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null; 
     } 
    } 
} 

Kopalnia pracuje ~ 200kb danych, 10 komunikaty wysłać konsekwentnie. Nie wiem, jak dobrze działa, jeśli jest więcej danych wysyłanych na sekundę.

+0

Świetna praca. fajne rozwiązanie. – No1Lives4Ever

+0

Nie wygrałem dla mnie. Może dlatego, że jest to aplikacja owinna z Web Api i Signalr, a konfiguracja musi być różnie skonfigurowana. –

+0

W przypadku, gdy SignalR znajduje się wewnątrz aplikacji Owin, powyższą odpowiedź należy połączyć z tym http://jerodkrone.com/signalr-2 -0-dependency-injection-using-globalhost/w celu działania. Jeśli koncentrator używa niestandardowej konfiguracji, takiej jak var hubconfig = new HubConfiguration(); i niestandardowy resolver, taki jak hubconfig.Resolver = new AutofacDependencyResolver (lifetimeScope); następnie w StartUp należy dodać 2 linie: GlobalHost.DependencyResolver = hubconfig.Resolver; GlobalHost.Configuration.MaxIncomingWebSocketMessageSize = null; –