c# - WCF WebService 中的 GZip 压缩

标签 c# wcf web-services gzip

我有一个托管在 IIS7.5 上的 .NET 3.5 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 header )

最佳答案

我这样做是为了使用带有 DataContract 的 WCF 来传输 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.Data = CompressedBinaryConverter.ToByteArray(data);

然后在你的客户端像这样调用它来转换回一个对象:

dt = (DataTable)CompressedBinaryConverter.ToObject(wdt.Data);

关于c# - WCF WebService 中的 GZip 压缩,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10125748/

相关文章:

c# - 禁用 MaskedTextBox 声音

c# - 异常的 WCF 客户端行为

c# - SharpSVN路径问题

c# - 如何检测 DataGridView CheckBox 事件变化?

web-config - 如何将 http 和 https 的 WCF 服务配置合并到一个 web.config 中?

c# - 我怎样才能在客户端保持与网络服务的 session ?

web-services - 如何在非常复杂的业务规则上实现 BDD?

java - 什么是事件驱动 io(上下文 : Apache MINA, JBoss Netty)?

c# - 为使用 Xamarin.Forms 构建的 Android 应用程序实现自动更新的正确方法

wcf - 我可以在传出MSMQ上重定向地址错误的邮件吗?