2017-06-02 1 views
0

Ich muss ein großes Objekt streamen. Ich kann nicht herausfinden, wie man es in Stücke schickt. Der gepostete Code funktioniert jedoch stream.Flush() wird nur einmal aufgerufen. Im Wesentlichen puffe ich das Objekt ab - nicht gut. Wie rufe ich stream.Flush() mehrmals? Wenn ich eine Sammlung hätte, könnte ich in einer Schleife streamen. Wie mache ich das mit einem großen Objekt?Streaming Json - PushStreamContent mit einem großen Objekt

SERVER CODE:

public async Task<HttpResponseMessage> ConvertToTiffAsync([FromBody] DocumentDto dto) 
       { 
        // THIS IS LARGE 
        var document = await _service.ConvertToTiffAsync(dto); 
        var response = Request.CreateResponse(); 
        response.Content = new PushStreamContent((stream, content, context) => 
        { 
         var serializer = new JsonSerializer(); 
         using (var writer = new StreamWriter(stream)) 
         { 
          using (var jsonTextWriter = new JsonTextWriter(writer)) 
          { 
           serializer.Serialize(jsonTextWriter, document); 
           stream.Flush(); // ONLY CALLED ONCE - NEED MANY CALLS 
          } 
         } 
        }); 
        return response; 
       } 

Client-Code (Streaming nicht hier geschieht, sondern muss):

using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true })) 
      { 
       client.Timeout = new TimeSpan(0, 5, 0); 
       var stringContent = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json"); 
       using (var httpRequest = new HttpRequestMessage(HttpMethod.Post, endpoint)) 
       { 
        httpRequest.Content = stringContent; 
        using (HttpResponseMessage response = await client.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)) 
        { 
         response.EnsureSuccessStatusCode(); 
         using (var streamReader = new StreamReader(await response.Content.ReadAsStreamAsync())) 
         using (var jsonReader = new JsonTextReader(streamReader)) 
         { 
          var serializer = new JsonSerializer(); 
          return await Task.Run(() => serializer.Deserialize<ConvertDocumentDto>(jsonReader)).ConfigureAwait(false); 
         } 
        } 
       } 
      } 
+0

Sie müssen nicht spülen. Was PushStreamContent tut, sind im Grunde genommen alle Daten, die direkt in den Client geschrieben werden, ohne den Inhalt zu puffern. Sind Sie sicher, dass die vollständige JSON-Darstellung im Speicher vorhanden ist? – ckuri

+0

Auch nach https://www.thomaslevesque.com/2013/11/30/uploading-data-with-httpclient-using-a-push-model/ Wenn Sie JSON streamen möchten, anstelle eines PushStreamContent könnten Sie einfach Verwenden Sie einen neuen ObjectContent (document, new JsonMediaTypeFormatter()), der dasselbe tun sollte, aber viel prägnanter ist. – ckuri

+0

@ckuri ... dieser Artikel konzentriert sich auf das Hochladen nicht herunterladen. Außerdem glaube ich nicht, dass die Daten gestreamt werden, bis flush() aufgerufen wird - zumindest sehe ich es so, wenn ich den Code ausführe. –

Antwort

0

Ihr Server-Code in Ordnung zu sein scheint. Ihr Client-Code scheint jedoch nicht in der Lage zu sein, ordnungsgemäß mit dem Server zu interagieren.

Wenn Sie die DocumentDto-Eingabe festlegen möchten, müssen Sie den JSON in die Anforderung und nicht in die Antwort schreiben. Wenn Sie die Serveraktion verwenden möchten, ohne den vollständigen JSON im Speicher zu haben, benötigen Sie einen JsonTextReader. So im Allgemeinen in der Client-Seite sollte sein:

Wenn Ihr DTO klein ist und es Ihnen nichts ausmacht die komplette JSON in Speicher statt client.PostAsync (url) auch client.PostAsJsonAsync nutzen könnten (url, dto), die sich im Namespace HttpClientExtensions befindet, wenn Sie System.Net.Http.Formatting.dll importieren.

+0

Sorry, aber ich habe den falschen Code für den Client veröffentlicht. Die eigentliche Code-ID ist jetzt da und wird nicht gesendet. –