Content-Disposition中的HttpClient编码错误

时间:2017-10-29 19:21:26

标签: 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);
}

这会产生以下请求:

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可能会按照某些标准运作,但无论如何,是否有解决方法?

更新:外部API不希望接受格式filename*=utf-8''Тест.jpg,它期望filename="Тест.jpg"

4 个答案:

答案 0 :(得分:1)

好的,我找到了一种强制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);

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

答案 1 :(得分:0)

不使用自己构建的标头,而是使用.NET库:

streamContent.Headers.ContentDisposition = 
    new System.Net.Http.Headers.ContentDispositionHeaderValue("form-data") { 
        Name = "image", 
        FileName = "Тест.jpg" };

根据web docsRFC5987创建标头。

Content-Disposition: form-data; name=image; filename="=?utf-8?B?0KLQtdGB0YIuanBn?="

答案 2 :(得分:0)

这是解决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也没有适当的支持来上传名称包含非ASCII字符的文件。 HttpClient确实可以按照某些标准工作,但是Java服务器并不关心该标准,而是希望使用UTF-8格式的标头。

答案 3 :(得分:0)

如果有帮助,您还可以删除“文件名*”

//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);
}