2016-10-11 15 views
3

進捗報告のある大きな(実際には数ギガバイトまで)大きなファイルのアップロードをサポートするために、hereのようにPushStreamContentでHttpClientを使用しました。 (TransferEncodingChunkedが設定されていないと、HttpClientがOutOfMemory例外をスローする

private void PushContent(Stream src, Stream dest, int length) 
    { 
     const int bufferLength = 1024*1024*10; 
     var buffer = new byte[bufferLength]; 
     var pos = 0; 
     while (pos < length) 
     { 
      var bytes = Math.Min(bufferLength, length - pos); 
      src.Read(buffer, 0, bytes); 
      dest.Write(buffer, 0, bytes); 
      pos += bufferLength; 
      dest.Flush(); 
      Console.WriteLine($"Transferred {pos} bytes"); 
     } 
     dest.Close(); 
    } 

しかし、最初に、このコードは、プロセスのメモリ消費量が非常に高くなかったにもかかわらず、320メガバイトを転送した後のOutOfMemory例外が発生しました:それは、私たちは二つの流れの間にバイトをコピーし、簡単な作品ここでのコード例であります約500MB)。だけでなく、私たちは、このフラグを設定して、巨大なファイルを転送することができました、メモリ消費量が90%減少し

request.Headers.TransferEncodingChunked = true; 

:何、この問題を修正することはTransferEncodingChunkedフラグを設定しています。

TransferEncodingChunkedの使用を必要とするドキュメントが見つかりませんでした。これは試行錯誤のプロセスですが、このシナリオでは非常に重要です。それでも私は例外が全くスローされない理由に困惑しています - メモリ消費量はそれほど高くなく、原因は何ですか?

+0

データが大きい場合は、それをチャンクで送信する方がよいでしょう、それは驚くべきことですか? – demonplus

+0

私はOutOfMemoryの驚くべき例外を早期に発見しました。 –

答えて

3

Chunked transfer encoding

チャンク転送符号化データ「チャンク」の 直列に送信されるハイパーテキスト転送プロトコル(HTTP)のバージョン1.1 のデータ転送メカニズムです。これは、Content-Lengthヘッダーの のところにTransfer-Encoding HTTPヘッダーを使用します。これは、別の方法では プロトコルの以前のバージョンで必要になります。 1 のContent-Lengthヘッダーが使用されていないため、送信者は受信者への応答の送信を開始する前に、コンテンツの長さを知る必要はありません。 送信者は、コンテンツの合計サイズを把握する前に、動的に生成されたコンテンツの送信を開始することができます。

受信者がその チャンクのデータの受信を完了したことを通知できるように、各チャンクのサイズがチャンクの直前に送信されます。データ転送は、長さが の最終チャンクで終了します。

論理的に考えると、ファイルは小さなチャンクで送信されます。つまり、チャンクで終了すると、メモリから解放されます。最終的には、複数の小さなチャンクを扱っているため、メモリ消費量は少なくなります。

+0

これは理にかなっており、なぜメモリ消費が減少するのかを説明しています。それでも、OutOfMemory例外がまったくスローされるのは不思議です。 PushStreamContentを使用せず、HttpClientによって完全に制御されたTranditional StreamContentを使用しても、例外は発生しません。 –

+1

@VagifAbilovなぜ、これは研究が必要なのか、それは別の質問です。この質問はhttp://stackoverflow.com/questions/16168683/webapi-streamcontent-vs-pushstreamcontentで確認できます。彼らは、プッシュストリームのコンテンツは、ストリームにデータをプッシュする必要があるときに使用していて、ストリームからプルする必要があるときにはコンテンツをストリームすると言っていました。 – mybirthname

+0

リンクをありがとう、非常に便利です。 –

関連する問題