C#中的HttpWebRequest POST请求失败

9

我正在尝试向Web服务器POST一些内容。

System.Net.HttpWebRequest EventReq = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create("url");
System.String Content = "id=" + Id;
EventReq.ContentLength = System.Text.Encoding.UTF8.GetByteCount(Content);
EventReq.Method = "POST";
EventReq.ContentType = "application/x-www-form-urlencoded";
System.IO.StreamWriter sw = new System.IO.StreamWriter(EventReq.GetRequestStream(), System.Text.Encoding.UTF8);
sw.Write(Content);
sw.Flush();
sw.Close();

看起来还好,我正在根据编码数据的大小设置内容长度... 无论如何,在sw.flush() 失败,显示“要写入流中的字节数超过指定的Content-Length大小”

StreamWriter是否在我不知道的情况下进行了一些魔法?有没有办法可以窥探StreamWriter正在做什么?

3个回答

23

其他答案已经解释如何避免这种情况,但我想回答一下为什么会发生这种情况:你在实际内容之前留下了一个字节顺序标记

你可以通过调用new UTF8Encoding(false)而不是使用Encoding.UTF8来避免这个问题。以下是一个简短的程序,演示了它们之间的区别:

using System;
using System.Text;
using System.IO;

class Test    
{
    static void Main()
    {
        Encoding enc = new UTF8Encoding(false); // Prints 1 1
        // Encoding enc = Encoding.UTF8; // Prints 1 4
        string content = "x";
        Console.WriteLine(enc.GetByteCount("x"));
        MemoryStream ms = new MemoryStream();
        StreamWriter sw = new StreamWriter(ms, enc);
        sw.Write(content);
        sw.Flush();
        Console.WriteLine(ms.Length);
    }

}

很好的发现。我想过挖掘,但是... <g> - Marc Gravell
您说得对 :) 这解释了我在另一条评论中关于Wireshark的观察。非常感谢! - KJ Tsanaktsidis

4
也许可以让生活更轻松:
using(WebClient client = new WebClient()) {
    NameValueCollection values = new NameValueCollection();
    values.Add("id",Id);
    byte[] resp = client.UploadValues("url","POST", values);
}

或者查看这里,了解允许像下面这样使用的讨论:

client.Post(destUri, new {
     id = Id // other values here
 });

2

您无需显式设置ContentLength,因为当您关闭请求流时,它将自动设置为写入请求流的数据大小。


你说得没错;这样修复了那个特定的问题。但是使用Wireshark查看发送的数据包会发现StreamWriter正在将某些内容添加到POST数据中...\357\273\277id=301Rbu 这3个字节从哪里来的??? 这个数据包中Content-Length设置为12。 - KJ Tsanaktsidis
2
@Jon Skeet 描述得很好(像往常一样 =))- 这就是所谓的“Unicode 字节顺序标记”,它标识文本是 UTF-8、UTF-16 大端序还是小端序等。在这里阅读更多信息 http://en.wikipedia.org/wiki/Byte-order_mark - elder_george

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接