public string PostXml(string url, string xmlContent)
{
if (string.IsNullOrEmpty(url)) throw new ArgumentException("URL 不可為空");
if (string.IsNullOrEmpty(xmlContent)) throw new ArgumentException("XML 內容不可為空");
byte[] buffer = Encoding.UTF8.GetBytes(xmlContent); // 必須與 XML 宣告 encoding 一致
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/xml; charset=utf-8"; // 關鍵:指定 charset
request.ContentLength = buffer.Length;
request.Timeout = 30000; // 30 秒
request.ReadWriteTimeout = 30000;
// 寫入請求串流
using (var reqStream = request.GetRequestStream())
{
reqStream.Write(buffer, 0, buffer.Length);
}
// 讀取回應
using (var response = (HttpWebResponse)request.GetResponse())
using (var respStream = response.GetResponseStream())
using (var reader = new StreamReader(respStream, Encoding.UTF8)) // 依回應實際編碼調整
{
return reader.ReadToEnd();
}
}
| 現象 | 原因 | 解決 |
|---|---|---|
| 中文亂碼 | 請求/回應編碼不一致 (XML 宣告 utf-8,但 GetBytes 用 Unicode/Default) | 統一用 Encoding.UTF8,ContentType 加 charset=utf-8 |
| 伺服器回傳 415 Unsupported Media Type | Content-Type 錯誤 | 確認 text/xml 或 application/xml,依 API 文件調整 |
| 大量資料 Timeout | 預設 100 秒可能不足 | 設定 Timeout、ReadWriteTimeout,或分批傳送 |
| Keep-Alive 導致連線耗盡 | 預設 KeepAlive=true,高併發時連線池滿 | request.KeepAlive = false 或調大 ServicePointManager.DefaultConnectionLimit |
public string PostXmlAdvanced(string url, string xmlContent, CookieContainer cookies = null)
{
byte[] buffer = Encoding.UTF8.GetBytes(xmlContent);
var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "text/xml; charset=utf-8";
request.ContentLength = buffer.Length;
request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; // 自動解壓
request.CookieContainer = cookies ?? new CookieContainer();
request.KeepAlive = false; // 短連線,避免佔用
using (var reqStream = request.GetRequestStream())
reqStream.Write(buffer, 0, buffer.Length);
using (var response = (HttpWebResponse)request.GetResponse())
{
// 依回應 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))
return reader.ReadToEnd();
}
}
// .NET 4.5+ / .NET Core 使用 HttpClient (推薦)
private static readonly HttpClient _httpClient = new HttpClient();
public async Task PostXmlAsync(string url, string xmlContent)
{
var content = new StringContent(xmlContent, Encoding.UTF8, "text/xml");
var response = await _httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
HttpClient 優點: 非同步原生、連線池自動管理、支援 `await`、可攜性佳。舊專案維護才用 `HttpWebRequest`。
原文提到發送 UTF-8 XML 時,使用 `Encoding.Unicode`/`Default`/`ASCII` 皆失敗,改用 `UTF8` 成功。並提供完整流程說明:建立 HttpWebRequest → 設定 Header/ContentType → 寫入 RequestStream → 取得 Response → 讀取 ResponseStream。
原文連結:https://www.bianceng.cn/Programming/csharp/201410/45576.htm