以下代码的目的是通过HTTP发布以字节顺序标记(BOM)开头的数据。
var client = new WebClient();
client.Encoding = new UTF8Encoding(true /* encoderShouldEmitUTF8Identifier */);
client.UploadString(url, data);
然而根据提琴手的说法,请求正文的开头没有BOM。即使我使用UnicodeEncoding
代替UTF8Encoding
,也不会发送BOM。
所以问题是,我做错了什么?
注意:我知道我可以通过将WebClient.UploadData
与Encoding.GetPreamble
方法结合使用来绕过此问题,但我想知道为什么UploadString
不起作用正如我所料。
答案 0 :(得分:1)
你没有做错任何事,只是WebClient.UploadString 没有调用Encoding.GetPreamble - 它只是在你传递的字符串上调用Encoding.GetBytes
。在HTTP请求中,如果您传递字符串,则通常会在内容类型标头(charset参数)中指示编码,而不是在文件中内联(请参阅下面的示例)。 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();
}
}