4

以下代码的目的是通过 HTTP 发布以字节顺序标记 (BOM) 开头的数据。

var client = new WebClient();
client.Encoding = new UTF8Encoding(true /* encoderShouldEmitUTF8Identifier */);
client.UploadString(url, data);

但是,根据提琴手的说法,请求正文的开头没有 BOM。即使我使用UnicodeEncoding而不是UTF8Encoding.

所以问题是,我做错了什么?

注意:我知道我可以通过WebClient.UploadData结合使用Encoding.GetPreamble方法来绕过这个问题,但是我想知道为什么UploadString不能按预期工作。

4

1 回答 1

1

你没有做错任何事,只是 WebClient.UploadString没有调用 Encoding.GetPreamble - 它只是调用Encoding.GetBytes你传递的字符串。在 HTTP 请求中,如果您传递字符串,您通常会在内容类型标头(字符集参数)中指示编码,而不是在文件中内联(参见下面的示例)。UploadString 这样做(它是为“常见情况”量身定制的)。正如你所提到的,如果你想要额外的东西,你可以直接上传字节。

public class StackOverflow_5731102
{
    [ServiceContract]
    public class Service
    {
        [WebInvoke]
        public Stream Process(Stream input)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var header in WebOperationContext.Current.IncomingRequest.Headers.AllKeys)
            {
                sb.AppendLine(string.Format("{0}: {1}", header, WebOperationContext.Current.IncomingRequest.Headers[header]));
            }

            string contentType = WebOperationContext.Current.IncomingRequest.ContentType;
            Encoding encoding = Encoding.GetEncoding(contentType.Substring(contentType.IndexOf('=') + 1));
            WebOperationContext.Current.OutgoingResponse.ContentType = WebOperationContext.Current.IncomingRequest.ContentType;
            return new MemoryStream(encoding.GetBytes(sb.ToString()));
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(baseAddress));
        host.Open();
        Console.WriteLine("Host opened");

        foreach (var encoding in new Encoding[] { new UTF8Encoding(true), new UnicodeEncoding(false, true) })
        {
            Console.WriteLine("Sending encoding = {0}", encoding.WebName);
            WebClient client = new WebClient();
            client.Headers[HttpRequestHeader.ContentType] = "text/plain; charset=" + encoding.WebName;
            client.Encoding = encoding;
            string url = baseAddress + "/Process";
            string data = "hello";
            string result = client.UploadString(url, data);
            Console.WriteLine(result);

            Console.WriteLine(string.Join(",", encoding.GetBytes(data).Select(b => b.ToString("X2"))));
        }

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }
}
于 2011-06-23T21:34:43.787 回答