簡體   English   中英

HttpClient 在 Content-Disposition 中編碼錯誤

[英]HttpClient wrong encoding in Content-Disposition

我正在使用HttpClient POST 圖像,它適用於具有拉丁名稱的文件,但只要名稱包含任何非 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"

好的,我找到了一種方法來強制MultipartFormDataContent忘記古老的 RFC 並改用 UTF8。 訣竅是使用反射來覆蓋內部靜態類HttpRuleParser定義的DefaultHttpEncoding

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

不確定可能導致哪些不良后果,但我想沒有。

這是在不篡改內部字段的情況下解決 HttpClient 限制的另一種方法。 受到這個答案的啟發。

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 格式的標頭。

不要添加您自己構建的標頭,而是使用 .NET 庫:

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

這會根據Web 文檔RFC5987創建標頭。

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

如果有幫助,您還可以刪除“文件名*”

//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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM