2016-08-19 15 views
4

私のプログラムはHttpClientを使用してWeb APIにGETリクエストを送信し、これがファイルを返します。メモリを経由せずにHttpResponseMessageからファイルに直接ストリームできますか?

私は今、ディスクにファイルを保存するために、このコード(簡体字)を使用します。このコードが実行されるとき

public async Task<bool> DownloadFile() 
{ 
    var client = new HttpClient(); 
    var uri = new Uri("http://somedomain.com/path"); 
    var response = await client.GetAsync(uri); 

    if (response.IsSuccessStatusCode) 
    { 
     var fileName = response.Content.Headers.ContentDisposition.FileName; 
     using (var fs = new FileStream("C:\test\" + fileName, FileMode.Create, FileAccess.Write, FileShare.None)) 
     { 
      await response.Content.CopyToAsync(fs); 
      return true; 
     } 
    } 

    return false; 
} 

、プロセスがメモリにファイルのすべてをロードします。私は実際にストリームがHttpResponseMessage.ContentからFileStreamにストリームされることを期待しています。そのため、ストリームのほんの一部がメモリに保持されます。

大容量のファイル(> 1GB)で使用する予定であるため、すべてのファイルをメモリに保存しなくても実現できますか?

理想的には、部分をバイト[]に読み込み、すべてのコンテンツが書き込まれるまでその部分をファイルストリームに書き込むことなくループしないでください。それはこのようになります

+0

見て - https://msdn.microsoft.com/en-us/library/system.web.http.hosting.ihostbufferpolicyselector(v=vs.118).aspx –

+1

'CopyToAsync'はあなたが何を記述しているのですか? (内部的には、応答からデータのチャンクを繰り返し読み込み、すべてのデータが転送されるまでファイルに書き込みます)、ファイル全体を一度にバッファリングする必要はありません。 – Iridium

+0

私はあまりにも思ったことは、メモリ消費量を見て、それは間違いなく私は避けたいメモリ内のファイル全体を読み込みます。 –

答えて

3

は、バイ・デザインです - あなたはHttpClient.GetAsync()のドキュメントをチェックすると、あなたはそれを言うわかります(コンテンツ含む)を

返されたタスクオブジェクトは全体の応答 後に完了します

を読まれる

代わりに、具体的に述べたHttpClient.GetStreamAsync()を使用することができます。

このメソッドはストリームをバッファしません。あなたは私の知る限り見ることができるように対応してヘッダーへのアクセスを得ることはありませんしかし

。これは恐らくヘッダーからファイル名を取得するときの要件なので、代わりにHttpWebRequestを使用して、レスポンスの詳細(ヘッダーなど)をメモリに読み込まずに取得できます。以下のような何か:要求が失敗した応答コードを返した場合、例外がスローされますので、あなたはtry..catchでラップし、元の例のように、この場合のfalseを戻したいことが

public async Task<bool> DownloadFile() 
{ 
    var uri = new Uri("http://somedomain.com/path"); 
    var request = WebRequest.CreateHttp(uri); 
    var response = await request.GetResponseAsync(); 

    ContentDispositionHeaderValue contentDisposition; 
    var fileName = ContentDispositionHeaderValue.TryParse(response.Headers["Content-Disposition"], out contentDisposition) 
     ? contentDisposition.FileName 
     : "noname.dat"; 
    using (var fs = new FileStream(@"C:\test\" + fileName, FileMode.Create, FileAccess.Write, FileShare.None)) 
    { 
     await response.GetResponseStream().CopyToAsync(fs); 
    } 

    return true 
} 

注意。

+0

説明をありがとう。実際、クライアント上でGetStreamAsyncを使用すると、ストリームをディスクではなくメモリに直接保存することができます。私たちはサーバーも制御できるので、まず別の要求でメタデータ(ファイル名、サイズ)を取得することができます。その後、私はヘッダーにアクセスする必要はありません。 –

関連する問題