HttpClient 在 Content-Disposition 中编码错误

Mon*_*nor 5 c# http content-disposition

我正在发布一个图像,HttpClient它适用于具有拉丁名称的文件,但是一旦名称包含任何非 ASCII 字符,它就会被转换为一系列问号。如果我创建一个 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);
}
Run Code Online (Sandbox Code Playgroud)

这会产生以下请求:

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...
Run Code Online (Sandbox Code Playgroud)

我知道这HttpClient可能会根据某些标准工作,但无论如何,有什么解决方法吗?

更新:外部 API 不想接受格式filename*=utf-8''????.jpg,它期望filename="????.jpg".

idi*_*lov 8

这是在不篡改内部字段的情况下解决 HttpClient 限制的另一种方法。受到这个答案的启发。

\n\n
using (var client = new HttpClient())\n{\n    var streamContent = new StreamContent(someImageFileStream);\n    streamContent.Headers.Add("Content-Disposition",\n        new string(Encoding.UTF8.GetBytes("form-data; name=\\"image\\"; filename=\\"\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82.jpg\\"").\n        Select(b => (char)b).ToArray()));\n\n    var content = new MultipartFormDataContent();\n    content.Add(streamContent);\n    await client.PostAsync("http://localhost.fiddler/", content);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我确认即使是 .net core 2.2 也没有适当支持上传名称包含非 ASCII 字符的文件。HttpClient 确实根据某些标准工作,但 Java 服务器不关心该标准并期望 UTF-8 格式的标头。

\n

  • “甚至 .net core 2.2 也没有适当的支持” MultipartFormDataContent\StreamContent 似乎按照规范(RFC)afaics 100%工作。问题是,似乎没有其他人这样做,甚至连 Microsoft 的旧东西(例如 HttpRequest\HttpPostedFile)也没有。我认为微软应该向 IETF 指出这一点,并将文件名编码为纯 utf8。 (3认同)

Mon*_*nor 2

好的,我找到了一种方法来强制MultipartFormDataContent忘记古老的 RFC 并使用 UTF8 代替。技巧是使用反射来覆盖DefaultHttpEncoding内部静态类中的定义HttpRuleParser

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

不确定可能会导致哪些不良后果,但我想没有。