[英]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.我正在使用HttpClient
POST 图像,它适用于具有拉丁名称的文件,但只要名称包含任何非 ASCII 字符,它就会转换为一系列问号。 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.如果我创建一个 html 表单并使用浏览器发布文件,则文件名以 UTF8 格式发送,目标服务器完全接受它。
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?我知道HttpClient
可能会根据某些标准工作,但无论如何,有什么解决方法吗?
UPDATE : The external API doesn't want to accept the format filename*=utf-8''Тест.jpg
, it expects filename="Тест.jpg"
.更新:外部 API 不想接受filename*=utf-8''Тест.jpg
格式,它需要filename="Тест.jpg"
。
OK, I've found a way to force MultipartFormDataContent
to forget the ancient RFCs and use UTF8 instead.好的,我找到了一种方法来强制MultipartFormDataContent
忘记古老的 RFC 并改用 UTF8。 The trick is to use reflection to overwrite the DefaultHttpEncoding
defined in the internal static class HttpRuleParser
.诀窍是使用反射来覆盖内部静态类HttpRuleParser
定义的DefaultHttpEncoding
。
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.不确定可能导致哪些不良后果,但我想没有。
This is another way to workaround the limitation of HttpClient without tampering with internal fields.这是在不篡改内部字段的情况下解决 HttpClient 限制的另一种方法。 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.我确认即使 .net core 2.2 也不支持上传名称包含非 ASCII 字符的文件。 HttpClient does work according to some standard but Java servers don't care about that standard and expect UTF-8 formatted headers. HttpClient 确实根据一些标准工作,但 Java 服务器不关心该标准并期望 UTF-8 格式的标头。
Instead of adding a header that you built yourself, use the .NET library:不要添加您自己构建的标头,而是使用 .NET 库:
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 .这会根据Web 文档和RFC5987创建标头。
Content-Disposition: form-data; name=image; filename="=?utf-8?B?0KLQtdGB0YIuanBn?="
If it helps, you can also remove the " filename *"如果有帮助,您还可以删除“文件名*”
//It deletes filename* parametr
foreach (var content in multipartContent) {
var headerContent = content.Headers.ContentDisposition.Parameters.Where(x => x.Name == "filename*").SingleOrDefault();
if(headerContent != null)
content.Headers.ContentDisposition.Parameters.Remove(headerContent);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.