LoginSignup
14
14

More than 5 years have passed since last update.

HttpClientでmultipart/form-dataでのファイル送信で日本語のファイル名が文字化けする

Last updated at Posted at 2018-01-10

使用環境

C#
.NET 4.0 (NugetでMicrosoft.Net.Httpをインストール済み)
※たぶん4.5以降も同じです。

やりたかったこと

WebApiをコンソールアプリから呼び出したかったんです。
でもWebClientクラスでは1回のPOST送信で複数ファイル送れないじゃない!

HttpClientならできる?でも.NET4.5以降のものだしなぁ・・・

と思ったらNugetで配信されてた(Microsoftさんありがとう!)

ファイル送信ソース

こちらさんの記事を参考にしながら下記を記述

Program.cs
using (var httpClient = new HttpClient())
using (var multipart = new MultipartFormDataContent())
{
    var finfo = new FileInfo(filePath); // ここは指定のファイルをどうぞ

    var fileContent = new StreamContent(File.OpenRead(finfo.FullName));
    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
    {
        Name = "file1", // ここは任意の名前で
        FileName = finfo.Name
    }

    multipart.Add(fileContent);

    // 送信
    var postAsyncTask = httpClient.PostAsync(reqestUrl, multipart);
    postAsyncTask.Wait(); // async/awaitは.NET4.0だから使えない...
    var responseMessage = postAsyncTask.Result;
}

ちなみに今回は"サンプルファイル.xlsx"というファイル名のファイルを送信している。

すると受け取り先で...

ファイル名が文字化け!
↓こんな感じ
=?utf-8?B?44K144Oz44OX44Or44OV44Kh44Kk44OrLnhsc3g=?=

対策

いろいろと調べると、勝手にHttpClientくんがファイル名とかを含んだContentDispositionをエンコードしちゃうらしい。
おそらくBase64でエンコードされる。

そこでStack Overflowくんのこの記事を参考にして、対策をおこなう。

Program.cs
using (var httpClient = new HttpClient())
using (var multipart = new MultipartFormDataContent())
{
    var finfo = new FileInfo(filePath); // ここは指定のファイルをどうぞ

    // 手動でエンコードを行う。
    string headerValue = string.Format("form-data; name=\"{0}\"; filename=\"{1}\"", "file1", finfo.Name);
    byte[] headerValueByteArray = Encoding.UTF8.GetBytes(headerValue);
    var encodingHeaderValue = new StringBuilder();
    foreach (byte b in headerValueByteArray)
    {
        encodingHeaderValue.Append((char)b);
    }

    fileContent.Headers.Add("Content-Disposition", encodingHeaderValue.ToString());

    multipart.Add(fileContent);

    // 送信
    var postAsyncTask = httpClient.PostAsync(reqestUrl, multipart);
    postAsyncTask.Wait(); // async/awaitは.NET4.0だから使えない...
    var responseMessage = postAsyncTask.Result;
}

自分のつたない英語力では「こんな感じで先にエンコードしてやるんやで」
ぐらいのニュアンスしかつかめなかったが、とりあえずこれで文字化けしなかったのでよしとする。

結論

HttpClientくんが余計なことをしてるので、こんな感じでやってあげよう。
もしかしたらNugetでHttpClientやWebClientの不便な部分を埋めると多分ヒットすると思う。(自分はむり)

先人の方たちの記事に感謝

14
14
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
14
14