2017-06-02 20 views
0

大きなオブジェクトをストリーミングする必要があります。私はそれをチャンクで送る方法を理解することができません。ただし、投稿されたコードはstream.Flush()が一度だけ呼び出されます。ですから、本質的に私はオブジェクトをバッファリングしています。 stream.Flush()複数回に電話するにはどうすればいいですか?私がコレクションを持っていれば、ループでストリーム/フラッシュできます。だから私はどのように大きなオブジェクトでそれを行うのですか?ストリーミングJson - 大きなオブジェクトを持つPushStreamContent

サーバコード:

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; 
       } 

クライアントコードは(ここでは起きていないストリーミングが、これらに必要):

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

フラッシュする必要はありません。 PushStreamContentの基本的なことは、基本的に、それに書き込まれるすべてのデータは、コンテンツをバッファリングせずに直接クライアントにストリーミングされることです。それで、完全なJSON表現がメモリにあることを確認してください。 – ckuri

+0

また、https://www.thomaslevesque.com/2013/11/30/uploading-data-with-httpclient-using-a-push-model/に従って、JSONをストリームしたい場合は、PushStreamContentの代わりに新しいObjectContent(document、new JsonMediaTypeFormatter())を使用してください。これは同じ作業を行う必要がありますが、はるかに簡潔です。 – ckuri

+0

@ckuri ...その記事はダウンロードしないアップロードに焦点を当てています。また、私は、データがflush()が呼び出されるまでストリーミングされているとは思っていません。少なくとも、コードを実行するときに見ている方法です。 –

答えて

0

お使いのサーバーのコードは大丈夫のようです。ただし、クライアントコードがサーバーと適切に対話できないようです。

DocumentDtoの入力を設定する場合は、リクエストではなくレスポンスにJSONを記述する必要があります。メモリ内に完全なJSONを持たずにサーバーアクションを使用するには、JsonTextReaderが必要です。だから、クライアント側では、一般的に次のようになります。

あなたのDTOが小さく、あなたの代わりにclient.PostAsync(URL)のメモリ内の完全なJSONを持つ気にしない場合もclient.PostAsJsonAsyncを使用することができますSystem.Net.Http.Formatting.dllをインポートすると、HttpClientExtensions名前空間にある(url、dto)

+0

申し訳ありませんが、クライアント用に間違ったコードを投稿しました。実際のコードIDは現在そこにあり、ストリームしません。 –

関連する問題