LoginSignup
68
54

More than 5 years have passed since last update.

HttpClient を使ってPOSTでマルチパートのファイルを送受信する

Last updated at Posted at 2015-07-16

.Net でクライアントから WebAPI に対しPOSTリクエストで複数のファイルをアップロードし、サーバからのレスポンスで複数ファイルをダウンロードする必要があったのでやってみた。

クライアントからのPOSTは HttpClient を使用する想定。

サーバサイドは ASP .Net MVC 4 WebAPI のPOSTでマルチパートのファイルを送受信する を参照。

やりたいこと

POST リクエスト
 ローカルに保存されたファイルを MultiPart の Content にして送信する

サーバからのレスポンス
 MultiPart でファイルが格納された Content をローカルに保存する

リクエストにファイルを含めて送る

送信側はネット上を調べたら比較的簡単にできた。

MultiPart の Content を作るには MultipartFormDataContent を生成し、File Content をAddしていく流れ。

var content = new MultipartFormDataContent();

File Content は File.OpenRead()で開いたファイルを StreamContent に食わせて Header にファイル名を設定してあげる。

var fileName = @"C:¥hogehoge.txt";
var fileContent = new StreamContent(File.OpenRead(fileName));
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
    FileName = Path.GetFileName(fileName)
};

content.Add(fileContent); // これをファイル数分繰り返す

あとは HttpClient の PostAsync() で送るだけ。

var httpClient = new HttpClient();
HttpResponseMessage response = httpClient.PostAsync(this.url, content).Result;

レスポンスからファイルを読み込む

今度はサーバから返ってきたレスポンスに MultiPart のファイルが含まれている場合に読み込んでローカルに保存する。ネット上にもなかなかまとまった情報がなくて苦労した。

MultiPart の読み込みには HttpContentMultipartExtensions という拡張メソッドを使うのがミソ。(.Net4.5 以上が必要っぽい)
参照設定の[アセンブリ][拡張] から「System.Net.Http.Formatting」を追加する。

まず HttpContentMultipartExtensions.ReadAsMultipartAsync() でレスポンスに渡された Content を provider に読み込む。

var provider = HttpContentMultipartExtensions.ReadAsMultipartAsync(response.Content).Result;

次に provider に読み込まれた Contents を1つずつ取り出す。
Content を取り出してしまえば、ReadAsStreamAsync() を呼び出してファイルの Stream を取得する。
保存用のファイルStreamを別途開き、CopyTo() でローカルに保存する。

foreach (var responseContent in provider.Contents)
{
    var fileName = responseContent.Headers.ContentDisposition.FileName;
    Stream stream = responseContent.ReadAsStreamAsync().Result;
    using (var outFileStream = new FileStream(@"C:\hoge" + Path.DirectorySeparatorChar + fileName, FileMode.Create, FileAccess.Write))
    {
        stream.CopyTo(outFileStream);
    }
}

上記例ではファイル決め打ちで処理しているが、いろいろ混ざっている場合は ContentType などを見てよしなに判断する。
ただ、ファイルの場合は ContentType が null なのでいきなり見ないように注意する。

if (responseContent.Headers.ContentType != null && responseContent.Headers.ContentType.ToString().Contains("text/plain"))
{
    // テキストのパラメータ
    string key = responseContent.Headers.ContentDisposition.Name;
    string value = responseContent.ReadAsStringAsync().Result;                            
}

書いてみるとたったこれだけの事か。。
特にクライアントサイドで MultiPart から Content を取り出す方法がなかなかわからなかったんだけど、わかってしまえば大したことはないな。

68
54
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
68
54