首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 修正中文亂碼的 HttpWebRequest POST XML 進階實作:UTF-8 編碼、自動解壓、連線池管理

     編輯:關於C#

完整健壯實作

public static XmlDocument PostXmlTransaction(string url, XmlDocument xmlDoc)
{
    if (string.IsNullOrEmpty(url)) throw new ArgumentException("URL 不可為空");
    if (xmlDoc == null) throw new ArgumentException("XML 文件不可為空");

    // 1. 設定連線池上限 (預設 2,高併發必調大)
    ServicePointManager.DefaultConnectionLimit = 200;
    ServicePointManager.Expect100Continue = false; // 減少 100-Continue 往返
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

    byte[] bytes = Encoding.UTF8.GetBytes(xmlDoc.OuterXml); // 含 XML 宣告

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = "POST";
    request.ContentType = "text/xml; charset=utf-8"; // 關鍵:明確指定 charset
    request.ContentLength = bytes.Length;
    request.Timeout = 60000;
    request.ReadWriteTimeout = 60000;
    request.KeepAlive = false; // 短連線,避免連線池耗盡
    request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; // 自動解壓回應
    request.ProtocolVersion = HttpVersion.Version11;

    // 2. 寫入請求串流
    using (var reqStream = request.GetRequestStream())
    {
        reqStream.Write(bytes, 0, bytes.Length);
    }

    // 3. 取得回應並解析 XML
    using (var response = (HttpWebResponse)request.GetResponse())
    {
        if (response.StatusCode != HttpStatusCode.OK)
            throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {response.StatusDescription}");

        // 依回應 Header 偵測編碼
        Encoding respEncoding = Encoding.UTF8;
        string contentType = response.ContentType;
        if (!string.IsNullOrEmpty(contentType))
        {
            var match = Regex.Match(contentType, @"charset\s*=\s*([\w-]+)", RegexOptions.IgnoreCase);
            if (match.Success)
            {
                try { respEncoding = Encoding.GetEncoding(match.Groups[1].Value); }
                catch { /* fallback UTF-8 */ }
            }
        }

        using (var respStream = response.GetResponseStream())
        using (var reader = new StreamReader(respStream, respEncoding))
        using (var xmlReader = XmlReader.Create(reader))
        {
            var responseDoc = new XmlDocument();
            responseDoc.Load(xmlReader);
            return responseDoc;
        }
    }
}

關鍵修正點對照

原文問題修正做法
Encoding.Unicode/GetBytes 導致亂碼統一使用 Encoding.UTF8,對應 XML ``
ContentType 缺少 charset設定 text/xml; charset=utf-8
回應編碼硬編碼 UTF-8解析 `Content-Type` Header `charset` 參數動態決定
無連線池管理設定 `DefaultConnectionLimit=200`、`KeepAlive=false`
無自動解壓`AutomaticDecompression = GZip | Deflate`
資源釋放不完整全程 `using` 區塊,確保 Stream/Response 正確 Dispose

HttpWebRequest 生命週期管理重點

  • GetRequestStream() 才會真正建立 TCP 連線並送出 Header。
  • GetResponse() 會阻塞等待伺服器回應 Header。
  • ResponseStream 讀取完畢前連線不會釋放回連線池。
  • 異常時必須 request.Abort() 強制釋放,否則連線池洩漏。

現代替代方案:HttpClient (強烈建議)

private static readonly HttpClient _client = new HttpClient
{
    Timeout = TimeSpan.FromSeconds(60)
};

public async Task PostXmlAsync(string url, XmlDocument xmlDoc)
{
    var content = new StringContent(xmlDoc.OuterXml, Encoding.UTF8, "text/xml");
    var response = await _client.PostAsync(url, content);
    response.EnsureSuccessStatusCode();

    string respXml = await response.Content.ReadAsStringAsync();
    var doc = new XmlDocument();
    doc.LoadXml(respXml);
    return doc;
}

HttpClient 內建連線池、自動解壓、非同步、可攜,除非維護 .NET Framework 4.0 以下舊專案,否則優先使用。

參考資源

原文連結:https://www.bianceng.cn/Programming/csharp/201410/45571.htm

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved