C# wcfwebservice中的GZip压缩
我在IIS7.5上有一个.NET3.5WebService 我有一个连接到此Web服务的客户端应用程序 我(在客户端应用程序中)更改了httpWebRequest.Create方法以添加GZip的自动压缩,但它不起作用C# wcfwebservice中的GZip压缩,c#,wcf,web-services,gzip,C#,Wcf,Web Services,Gzip,我在IIS7.5上有一个.NET3.5WebService 我有一个连接到此Web服务的客户端应用程序 我(在客户端应用程序中)更改了httpWebRequest.Create方法以添加GZip的自动压缩,但它不起作用 WebRequest IWebRequestCreate.Create(Uri uri) { HttpWebRequest httpWebRequest = Activator.CreateInstance(
WebRequest IWebRequestCreate.Create(Uri uri)
{
HttpWebRequest httpWebRequest =
Activator.CreateInstance(
typeof(HttpWebRequest),
BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { uri, null },
null) as HttpWebRequest;
if (httpWebRequest == null)
return null;
httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
return httpWebRequest;
}
通过这种方式,请求被正确发送,答案被编码为gzip(我从Fiddler那里看到),但出现了异常:
Response is not wellformed XML
(我认为客户没有解码答案)
如果删除此行,如MSDN文档中所示
httpWebRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip, deflate");
答案不是GZip编码的(并且在请求中没有ACCEPT-ENCODING头)如果您同时控制客户端和服务器,一种可能的方法是使用WCF服务实现压缩 我这样做是为了使用WCF和DataContract传输DataTable对象。您必须按如下方式创建DataContract:
[DataContract]
public class WCFDataTableContract
{
[DataMember]
public byte[] Schema { get; set; }
[DataMember]
public byte[] Data { get; set; }
}
然后我创建了一个二进制转换器,它将自动将任何对象转换为字节数组,然后我可以使用GZip进行压缩
public static class CompressedBinaryConverter
{
/// <summary>
/// Converts any object into a byte array and then compresses it
/// </summary>
/// <param name="o">The object to convert</param>
/// <returns>A compressed byte array that was the object</returns>
public static byte[] ToByteArray(object o)
{
if (o == null)
return new byte[0];
using (MemoryStream outStream = new MemoryStream())
{
using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress))
{
using (MemoryStream stream = new MemoryStream())
{
new BinaryFormatter().Serialize(stream, o);
stream.Position = 0;
stream.CopyTo(zipStream);
zipStream.Close();
return outStream.ToArray();
}
}
}
}
/// <summary>
/// Converts a byte array back into an object and uncompresses it
/// </summary>
/// <param name="byteArray">Compressed byte array to convert</param>
/// <returns>The object that was in the byte array</returns>
public static object ToObject(byte[] byteArray)
{
if (byteArray.Length == 0)
return null;
using (MemoryStream decomStream = new MemoryStream(byteArray), ms = new MemoryStream())
{
using (GZipStream hgs = new GZipStream(decomStream, CompressionMode.Decompress))
{
hgs.CopyTo(ms);
decomStream.Close();
hgs.Close();
ms.Position = 0;
return new BinaryFormatter().Deserialize(ms);
}
}
}
}
然后在客户端像这样调用它以转换回对象:
dt = (DataTable)CompressedBinaryConverter.ToObject(wdt.Data);
解决了!!
问题中的代码足以作为服务参考。
如果您使用的是Web引用,请同时添加该行
my_service_object.EnableDecompression = true;
IIS应该可以向任何托管服务添加压缩支持。没有办法通过自定义编码实现GZip压缩。。好啊如何在WCF Web服务中使用GZip压缩?因为我必须传输大量的文本数据。大约2-3年前,我经历了整个痛苦的过程。我一直在努力找到解决办法,但到目前为止运气不好+更新:我找到了二进制文件,并设法通过Reflector查看代码。在我的例子中,我只设置了
自动压缩
,没有其他设置。我将查看是否涉及其他代码。我已经浪费了很多时间尝试实现它,但没有成功。嗯,我们在c#server和Java客户机中都实现了自定义数据压缩。这个协议对所有使用过它的人来说都是一个巨大的痛苦,这里有很多限制。但无论如何,你都不能将其用于公共合同。问题表明,他们控制着双方,即客户机和服务器。你能给我指一下“大痛苦”这篇文章或一些我能更好地了解问题所在的摘要吗?简单的一点是,如果你发送一个空集合,你将收到空集合,而不是相同的空集合。是的,这就是我要解决的问题。。但这有一个问题:源对象和目标对象是不同类的实例(因为Web服务的名称空间不同),我将服务器和客户端之间共享的任何对象定义放在单独的DLL中,并从服务器和客户端引用它们。这样,您只需在一个地方定义/维护它,并且您的定义是通用的。
my_service_object.EnableDecompression = true;