Search code examples
c#httpcontent-disposition

HttpClient wrong encoding in Content-Disposition


I am POST-ing an image with HttpClient and it works well for files with Latin names, but as soon as a name contains any non-ASCII characters it gets transformed to a sequence of question marks. If I create an html form and use a browser to post the file, the file name is sent in UTF8 and the target server perfectly accepts it.

using (var client = new HttpClient())
{
    var streamContent = new StreamContent(someImageFileStream);
    streamContent.Headers.Add(
        "Content-Disposition",
        "form-data; name=\"image\"; filename=\"Тест.jpg\"");

    var content = new MultipartFormDataContent();
    content.Add(streamContent);

    await client.PostAsync("http://localhost.fiddler/", content);
}

This produces the following request:

POST http://localhost/ HTTP/1.1
Content-Type: multipart/form-data; boundary="e6fe89be-e652-4fe3-8859-8c7a339c5550"
Host: localhost
Content-Length: 10556

--e6fe89be-e652-4fe3-8859-8c7a339c5550
Content-Disposition: form-data; name="image"; filename="????.jpg"

...here goes the contents of the file...

I understand that HttpClient might work according to some standard, but anyway, is there any workaround?

UPDATE: The external API doesn't want to accept the format filename*=utf-8''Тест.jpg, it expects filename="Тест.jpg".


Solution

  • OK, I've found a way to force MultipartFormDataContent to forget the ancient RFCs and use UTF8 instead. The trick is to use reflection to overwrite the DefaultHttpEncoding defined in the internal static class HttpRuleParser.

    typeof(HttpClient)
      .Assembly
      .GetType("System.Net.Http.HttpRuleParser")
      .GetField("DefaultHttpEncoding", BindingFlags.Static | BindingFlags.NonPublic)
      .SetValue(null, System.Text.Encoding.UTF8);
    

    Not sure which bad consequences that might cause, but I suppose there are none.