问题
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"
.
回答1:
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.
回答2:
Instead of adding a header that you built yourself, use the .NET library:
streamContent.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") {
Name = "image",
FileName = "Тест.jpg" };
That creates the header per the web docs and RFC5987.
Content-Disposition: form-data; name=image; filename="=?utf-8?B?0KLQtdGB0YIuanBn?="
回答3:
This is another way to workaround the limitation of HttpClient without tampering with internal fields. Inspired by this answer.
using (var client = new HttpClient())
{
var streamContent = new StreamContent(someImageFileStream);
streamContent.Headers.Add("Content-Disposition",
new string(Encoding.UTF8.GetBytes("form-data; name=\"image\"; filename=\"Тест.jpg\"").
Select(b => (char)b).ToArray()));
var content = new MultipartFormDataContent();
content.Add(streamContent);
await client.PostAsync("http://localhost.fiddler/", content);
}
I confirm that even .net core 2.2 doesn't have proper support for uploading files whose names contain non-ASCII characters. HttpClient does work according to some standard but Java servers don't care about that standard and expect UTF-8 formatted headers.
来源:https://stackoverflow.com/questions/47004296/httpclient-wrong-encoding-in-content-disposition