C# wcfwebservice中的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(

我在IIS7.5上有一个.NET3.5WebService

我有一个连接到此Web服务的客户端应用程序

我(在客户端应用程序中)更改了httpWebRequest.Create方法以添加GZip的自动压缩,但它不起作用

 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;