「C Sharpとネットワーク - HttpClient」の版間の差分

285行目: 285行目:
<br>
<br>
==== POST : バイナリファイル ====
==== POST : バイナリファイル ====
POSTリクエストは、テキストファイルやPDFファイル等のバイナリファイルをアップロードすることができる。<br>
バイナリファイルを送信するためには、MIMEタイプを<code>multipart/form-data</code>に指定する。<br>
<br>
以下の例では、マルチパートで区切ることにより、複数のデータを送信している。<br>
マルチパートの1つ目は<code>StringContent</code>型でテキストデータ、マルチパートの2つ目は<code>StreamContent</code>型でバイナリファイルのデータである。<br>
これら2つのデータをボディ部に設定して、POSTリクエストで送信している。<br>
<syntaxhighlight lang="c#">
// テキストデータおよびバイナリデータをボディ部にセットして、POSTリクエストを送受信する。
// filePath : アップロードするバイナリファイルのパス
public string PostPdfFile(string filePath)
{
    String requestEndPoint = this.baseUrl + "resume/upload";
    var request = this.CreateRequest(HttpMethod.Post, requestEndPoint);
    // Accept: multipart/form-dataを指定
    request.Headers.Remove("Accept");
    request.Headers.Add("Accept", "multipart/form-data");
    // 生成するボディ部
    // Content-Type  : multipart/form-data; boundary = "{MultipartFormDataContentクラスが自動で設定}"
    // Content-Length: {MultipartFormDataContentクラスが自動で設定}
    var content = new MultipartFormDataContent();
    // ボディ部1に--boundaryで区切られたマルチパートのテキストデータを追加
    // --boundary
    // Content-Type: text/plain; charset=utf-8
    // Content-Disposition: form-data; name=SamplePart
    //
    // Sample
    var multiDocumentsContent = new StringContent("Sample");
    content.Add(multiDocumentsContent, "SamplePart");
    StreamContent streamContent = null;
    var resStatusCoode = HttpStatusCode.NotFound;
    Task<HttpResponseMessage> response;
    String resBodyStr;
    using (var fileStream = File.OpenRead(filePath))
    {
      streamContent = new StreamContent(fileStream);
      // {Content-Disposition: form-data; name=file; filename="{ファイル名}"]
      //streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
      //{
      //  Name = "file",
      //  FileName = Path.GetFileName(filePath)
      //};
      // ファイル名がマルチバイト文字の場合は文字化けするため、ファイル名を手動でエンコードしてヘッダを別に作成する
      var finfo = new FileInfo(filePath);
      var headerStr = string.Format("form-data; name=\"file\"; filename=\"{0}\"", finfo.Name);
      var headerValueByteArray = Encoding.UTF8.GetBytes(headerStr);
      var encodedHeaderValue = new StringBuilder();
      foreach (var b in headerValueByteArray)
      {
          encodedHeaderValue.Append((char)b);
      }
      streamContent.Headers.ContentDisposition = null; // デフォルトで用意されているので一旦削除
      streamContent.Headers.Add("Content-Disposition", encodedHeaderValue.ToString());
      // バイナリファイル (PDFファイル)
      streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
      streamContent.Headers.Add("Content-Length", fileStream.Length.ToString());
      content.Add(streamContent, "file");
      // 生成するボディ部
      // ボディ部2に--boundaryから--boundary--までで区切られたマルチパートのバイナリデータを追加
      // --boundary
      // Content-Disposition: form-data; name="file"; filename="{エンコードされたファイル名}"
      // Content-Type: application/pdf
      // Content-Length: {上で計算された値}
      //
      // {バイナリファイルの実体}
      // --boundary--
      // 2つの部分を加えたボディ部をPOSTリクエストとして送信する
      request.Content = content;
      try
      {
          response = httpClient.SendAsync(request);
          resBodyStr = response.Result.Content.ReadAsStringAsync().Result;
          resStatusCoode = response.Result.StatusCode;
      }
      catch (HttpRequestException e)
      {  // 通信が失敗した場合
          return null;
      }
      fileStream.Close();
    }
    if (!resStatusCoode.Equals(HttpStatusCode.OK))
    {  // レスポンスが200以外の場合
      return null;
    }
    if (String.IsNullOrEmpty(resBodyStr))
    {  // レスポンスのボディが空の場合
      return null;
    }
    return resBodyStr;
}
</syntaxhighlight>
<br>


<br>
==== MIMEタイプ (コンテンツタイプ) ====
==== MIMEタイプ (コンテンツタイプ) ====
application/x-www-form-urlencodedおよびmultipart/form-dataは、HTTPのPOSTリクエストでデータを送信するための異なるMIMEタイプである。<br>
application/x-www-form-urlencodedおよびmultipart/form-dataは、HTTPのPOSTリクエストでデータを送信するための異なるMIMEタイプである。<br>