Content-Disposition 中的 HttpClient 编码错误
HttpClient wrong encoding in Content-Disposition
我正在 POST-ing 一张带有 HttpClient
的图像,它适用于具有拉丁名称的文件,但只要名称包含任何非 ASCII 字符,它就会转换为序列的问号。如果我创建一个 html 表单并使用浏览器访问 post 文件,文件名以 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);
}
这会产生以下请求:
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...
我知道 HttpClient
可能会根据某些标准工作,但无论如何,有什么解决方法吗?
UPDATE:外部 API 不想接受格式 filename*=utf-8''Тест.jpg
,它期望 filename="Тест.jpg"
.
不要添加您自己构建的 header,而是使用 .NET 库:
streamContent.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") {
Name = "image",
FileName = "Тест.jpg" };
根据 web docs and RFC5987 创建 header。
Content-Disposition: form-data; name=image; filename="=?utf-8?B?0KLQtdGB0YIuanBn?="
好的,我找到了一种强制 MultipartFormDataContent
忘记古老的 RFC 并改用 UTF8 的方法。诀窍是使用反射覆盖内部静态 class HttpRuleParser
.
中定义的 DefaultHttpEncoding
typeof(HttpClient)
.Assembly
.GetType("System.Net.Http.HttpRuleParser")
.GetField("DefaultHttpEncoding", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, System.Text.Encoding.UTF8);
不确定可能导致哪些不良后果,但我想有none。
这是在不篡改内部字段的情况下解决 HttpClient 限制的另一种方法。灵感来自 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);
}
我确认即使是 .net core 2.2 也不能正确支持上传名称包含 non-ASCII 个字符的文件。 HttpClient 确实根据某些标准工作,但 Java 服务器不关心该标准并期望 UTF-8 格式 headers.
如果有帮助,您还可以删除“文件名*”
//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);
}
我正在 POST-ing 一张带有 HttpClient
的图像,它适用于具有拉丁名称的文件,但只要名称包含任何非 ASCII 字符,它就会转换为序列的问号。如果我创建一个 html 表单并使用浏览器访问 post 文件,文件名以 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);
}
这会产生以下请求:
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...
我知道 HttpClient
可能会根据某些标准工作,但无论如何,有什么解决方法吗?
UPDATE:外部 API 不想接受格式 filename*=utf-8''Тест.jpg
,它期望 filename="Тест.jpg"
.
不要添加您自己构建的 header,而是使用 .NET 库:
streamContent.Headers.ContentDisposition =
new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") {
Name = "image",
FileName = "Тест.jpg" };
根据 web docs and RFC5987 创建 header。
Content-Disposition: form-data; name=image; filename="=?utf-8?B?0KLQtdGB0YIuanBn?="
好的,我找到了一种强制 MultipartFormDataContent
忘记古老的 RFC 并改用 UTF8 的方法。诀窍是使用反射覆盖内部静态 class HttpRuleParser
.
DefaultHttpEncoding
typeof(HttpClient)
.Assembly
.GetType("System.Net.Http.HttpRuleParser")
.GetField("DefaultHttpEncoding", BindingFlags.Static | BindingFlags.NonPublic)
.SetValue(null, System.Text.Encoding.UTF8);
不确定可能导致哪些不良后果,但我想有none。
这是在不篡改内部字段的情况下解决 HttpClient 限制的另一种方法。灵感来自 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);
}
我确认即使是 .net core 2.2 也不能正确支持上传名称包含 non-ASCII 个字符的文件。 HttpClient 确实根据某些标准工作,但 Java 服务器不关心该标准并期望 UTF-8 格式 headers.
如果有帮助,您还可以删除“文件名*”
//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);
}