LoginSignup
6
5

More than 3 years have passed since last update.

C#でHTTP POSTに複数コンテンツを含める

Last updated at Posted at 2020-11-28

この記事で解説すること

C#での複数コンテンツのPost方法を実例付きで解説する。
(複数コンテンツというのは、例えば、画像データとその名前の2つなどの事です。)

複数コンテンツのHTTP POSTの実現方法

以下を使うと複数コンテンツのPOSTが行えます。

要は、MultipartFromDataContenctにデータを追加していき、HttpClientのPostAsyncメソッドの引数として渡すだけです。(MultipartFormDataContentはHttpContentクラスを継承している)

実践-条件

それではやり方の一例を見ていきます。
今回は、以下のコンテンツをPostで送りたいとします。

Postで送るもの

  • 画像データと、その名前を一度にPostする
    • 画像データ(image):バイナリデータ
    • データ名(name):"hogehoge"

Post結果の確認方法

今回の例では、Post結果の確認にhttpbinを使わせてもらいます。
httpbinは、指定のURLにHTTPリクエストを送ると、送信されたパラメータなどの情報をレスポンスとして返してくれるWebサービス&ソフトウェアです。

以下のJsonがPostのResponseとして返ってくれば成功

今回の場合は、http://httpbin.org/post にPOSTリクエストを送り、以下のようなJSONがReponseとして返ってくれば成功です。
確認するポイントは2つです。

  • "files"内の"image"に指定したデータ(今回だと画像をバイト配列として送るのでバイト配列)が入っているかどうか
  • "form"内の"name"に指定した名前(hogehoge)が入っているどうか

{
    "args": {},
    "data": "",
    "files": {
        "image": "(~byteの羅列がここに入る。長いので省略~)"
    },
    "form": {
        "name": "hogehoge"
    },
    "headers": {
        "Content-Length": "13515",
        "Content-Type": "multipart/form-data; boundary="5cc407cc-3e4e-4d4a-8f67-fd2f29436423"",
        "Host": "httpbin.org",
        "X-Amzn-Trace-Id": "Root=1-5fc1ad93-3233ba1c3f705dd867fdf9c9"
    },
    "json": null,
    "origin": "126.99.210.176",
    "url": "http://httpbin.org/post"
}

実行環境

  • Windows10
  • C#8.0 (.NET Core3.1)

実践

本題のコードが以下です。


// MultipartFormDataContentのインスタンスをつくる。
using MultipartFormDataContent multiContent = new MultipartFormDataContent();

// コンテンツを、それぞれ専用の形式でインスタンス化する。
// imageBytes変数には本当は画像をバイナリ化したものが代入されている想定。
// ここでは簡単のため適当なバイナリを入れておく。
using ByteArrayContent imageContent = new ByteArrayContent(new byte[4] { 0, 1, 2, 3 });
using StringContent nameContent = new StringContent("hogehoge");

// 専用の形式にしたコンテンツを、MultipartFormDataContentにAddしていく。
multiContent.Add(imageContent, "image", "imageData");
multiContent.Add(nameContent, "name");

// HttpClientでPostする。
// (本当はHttpClientは都度インスタンスを生成するのではなく、アプリケーション内で使いまわしたほうがよい。)
using HttpClient client = new HttpClient();
var uri = new Uri("http://httpbin.org/post");
var msg = await client.PostAsync(uri, multiContent );

// Responseの表示
var responseContent = await msg.Content.ReadAsStringAsync();
Console.WriteLine($"{responseContent}");

コードについて解説していきます。

  • MultipartFormDataContentのインスタンスをつくる
// MultipartFormDataContentのインスタンスをつくる。
using MultipartFormDataContent multiContent = new MultipartFormDataContent();

ここは特に解説の必要もないと思います。
MultipartFormDataContentの派生大元であるHttpContentクラスはIDisposableを継承しているので、usingをつけて勝手に開放してくれるようにしておきます。
(この記事の趣旨とは関係ないですが、C#8.0から、using変数宣言により、その変数のスコープに基づいて自動開放してくれるようになりました。usingステートメントによる多重{}はコードが見にくくなるので、ここではusing変数宣言を使っています。)

  • コンテンツをそれぞれ専用の形式でインスタンス化する
// コンテンツを、それぞれ専用の形式でインスタンス化する。
// imageBytes変数には本当は画像をバイナリ化したものが代入されている想定。
// ここでは簡単のため適当なバイナリを入れておく。
using ByteArrayContent imageContent = new ByteArrayContent(new byte[4] { 0, 1, 2, 3 });
using StringContent nameContent = new StringContent("hogehoge");

MultipartFormDataContentに追加していく(もといHttpClientのコンテントとして扱う)ためには、各種コンテンツを専用の形式にしていく必要あります。
専用の形式とは、System.Net.Http.HttpClientクラスの派生クラスのことです。

ここでは、画像データ(それを事前にバイナリ化したもの)と文字列をそれぞれHttpContent化します。画像データはByteArrayContentクラス、文字列はStringContentクラスでHttpContent化します。(ここでは結果が見やすいよう画像データには適当なバイナリをいれてます。)

この部分は送りたいデータの形式に合わせて変えます。(他にはStreamContentクラスや、JsonContentクラスがあります。詳細はHttpContentクラスのドキュメントを読んでください。)

ちなみに、MultipartFormDataContentクラスももちろんHttpContentクラスの派生クラスです。(正確にはMultipartFormDataContentクラス → MultipartContentクラス → HttpContentクラスという継承関係)

  • 専用の形式にしたコンテンツをMultipartFormDataContentにAddしていく
// 専用の形式にしたコンテンツを、MultipartFormDataContentにAddしていく。
multiContent.Add(imageContent, "image", "imageData");
multiContent.Add(nameContent, "name");

上で専用の形式(HttpContentクラスの派生クラス)にしたデータを追加していくだけです。
MultipartFormDataContent.Add(HttpContent, string)メソッドを使って追加していきます。

ここで、画像データと文字列データでは、引数の異なるAdd()メソッドを使っています。

MultipartFormDataContent.Add()メソッドには、引数のとり方が3種類あります。

  1. HttpContentのみ
  2. HttpContentとString(HTTPコンテンツの名前)
  3. HttpContentとStringとString(HTTPコンテンツの名前とコレクションに追加する HTTP コンテンツのファイル名)

1, 2番目の方法だとコンテンツがRequestの"form"に含まれ、3番目の方法だとコンテンツがRequestの"files"に含まれます。

今回は、画像データは"files"に含まれて欲しいので3番目、文字列データは"forms"に含まれて欲しいので2番目のメソッドを使います。なお、3番目の方法の場合は、引数の3つ目に文字列が必要ですがこれは今回の場合何でもよいです。
(ちなみに1番目の方法を使った場合は、コンテンツはform"に含まれ、そのkeyにあたるものがnullとなります。)

  • POSTする
// HttpClientでPostする。
// (本当はHttpClientは都度インスタンスを生成するのではなく、アプリケーション内で使いまわしたほうがよい。)
using HttpClient client = new HttpClient();
var uri = new Uri("http://httpbin.org/post");
var msg = await client.PostAsync(uri, multiContent );

// Responseの表示
var responseContent = await msg.Content.ReadAsStringAsync();
Console.WriteLine($"{responseContent}");

通常通りHttpClientのPostAsync()メソッドを使ってPostするだけです。
(上のコードではPostとそのResponseの表示をしています。)

結果
コードを実行すると以下がResponseとして返ってきました。
大丈夫そうですね。

  • "files"内の"image"に指定したデータが入っている("\u0000\u0001\u0002\u0003"は1, 2, 3, 4をそれぞれ16進数表記にしたもの)
  • "form"内の"name"に指定した名前(hogehoge)が入っている

{
    "args": {},
    "data": "",
    "files": {
        "image": "\u0000\u0001\u0002\u0003"
    },
    "form": {
        "name": "hogehoge"
    },
    "headers": {
        "Content-Length": "13515",
        "Content-Type": "multipart/form-data; boundary="5cc407cc-3e4e-4d4a-8f67-fd2f29436423"",
        "Host": "httpbin.org",
        "X-Amzn-Trace-Id": "Root=1-5fc1ad93-3233ba1c3f705dd867fdf9c9"
    },
    "json": null,
    "origin": "126.99.210.176",
    "url": "http://httpbin.org/post"
}

まとめ

この記事では、C#での複数コンテンツのPost方法を実例付きで解説しました。

簡単にやり方をまとめると以下です。

  • MultipartFormDataContentのインスタンスをつくる
  • コンテンツをそれぞれ専用の形式でインスタンス化する
  • 専用の形式にしたコンテンツをMultipartFormDataContentにAddしていく
    • 追加したい形式によって複数あるAddメソッドを使い分ける
  • POSTする

リンク

6
5
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
6
5