Asp.net 如何在IIS 7上为SOAP Web服务的POST(上载)请求启用GZIP压缩?

Asp.net 如何在IIS 7上为SOAP Web服务的POST(上载)请求启用GZIP压缩?,asp.net,web-services,iis-7,http-compression,Asp.net,Web Services,Iis 7,Http Compression,如何对上载到.NET Web服务(SOAP,而不是WCF)的发布数据启用压缩?我原以为在IIS中只需要简单的操作,但启用后,它只是压缩响应,而不是POST请求 我已将其添加为服务引用,但在生成的SOAPClient上找不到任何设置来启用请求压缩 似乎我在客户端缺少一个配置设置或代码,以便在将请求发送到服务器之前对其进行压缩?或者我正在尝试做的(gzip发布数据)甚至不受支持 更多信息:我正在客户端和服务器上使用.NET 4.0。我在4年前就写过这方面的博客 我想知道你为什么没有在谷歌上找到这个

如何对上载到.NET Web服务(SOAP,而不是WCF)的发布数据启用压缩?我原以为在IIS中只需要简单的操作,但启用后,它只是压缩响应,而不是POST请求

我已将其添加为服务引用,但在生成的SOAPClient上找不到任何设置来启用请求压缩

似乎我在客户端缺少一个配置设置或代码,以便在将请求发送到服务器之前对其进行压缩?或者我正在尝试做的(gzip发布数据)甚至不受支持


更多信息:我正在客户端和服务器上使用.NET 4.0。

我在4年前就写过这方面的博客


我想知道你为什么没有在谷歌上找到这个。无论如何,这应该对你有用,我们已经让它在生产环境中工作了4年了。

最后,我使用了Wiktor Zychla的答案,但遇到了几个bug(在他的文章评论中也提到了)。为了完整起见,我将在这里发布我的HttpCompression模块的固定版本,但是您需要的其余代码(和实现指南)都在这里

更新:

实际上,我不得不停止使用这段代码,因为它有一个我无法修复的bug(即使使用下面改进的版本)。对于许多使用代理服务器的人来说,它会出现一个错误,即“gzip头中的魔法数字不正确”,我不知道如何解决这个问题。我认为这是因为代理服务器解压GZIP,而这段代码不允许以当前形式接收压缩和非压缩响应

using System;
using System.IO.Compression;
using System.Web;
using System.Web.Security;

/// <summary>
/// Implement two way HTTP compression for the SOAP API
/// Code taken from: http://netpl.blogspot.co.uk/2009/07/aspnet-webservices-two-way-    response-and.html
/// Fix: Set Content-encoding: gzip header when an Exception occurs on the server.
/// Fix: Do not attempt to decrypt GZIP request stream when request was not GZIPed.
/// </summary>
public class HttpCompressionModule : IHttpModule
{
    private bool isDisposed = false;

    ~HttpCompressionModule()
    {
            Dispose(false);
    }

    public void Init(HttpApplication context)
    {
            context.BeginRequest += new EventHandler(Context_BeginRequest);
            context.PreSendRequestHeaders += new EventHandler(context_PreSendRequestHeaders);
    }

    void context_PreSendRequestHeaders(object sender, EventArgs e)
    {
            // Fix headers having been lost if an exception occurred.
            HttpApplication app = sender as HttpApplication;
            HttpContext ctx = app.Context;
            if (app.Response.Filter is GZipStream) SetEncoding("gzip");
            else if (app.Response.Filter is DeflateStream) SetEncoding("deflate");

            // Fix double header
            if (ctx.Response.Headers["Content-encoding"] == "gzip,gzip")
                    ctx.Response.Headers.Set("Content-encoding", "gzip");
    }

    public void Context_BeginRequest(object sender, EventArgs e)
    {
            HttpApplication app = sender as HttpApplication;
            HttpContext ctx = app.Context;

            // Currently only enable for the Uploader API webservice
            if (!ctx.Request.Url.PathAndQuery.ToLower().Contains("uploaderapi.asmx"))
            {
                    return;
            }

            // Add request filter if request was GZIP encoded
            string requestEncoding = ctx.Request.Headers["Content-encoding"];
            if (requestEncoding != null && requestEncoding == "gzip")
            {
               app.Request.Filter =
                    new System.IO.Compression.GZipStream(app.Request.Filter, CompressionMode.Decompress);
            }

            // Add response compression filter if the client accepts compressed responses
            if (IsEncodingAccepted("gzip"))
            {
                    app.Response.Filter = new GZipStream(app.Response.Filter, CompressionMode.Compress);
                    SetEncoding("gzip");
            }
            else if (IsEncodingAccepted("deflate"))
            {
                    app.Response.Filter = new DeflateStream(app.Response.Filter, CompressionMode.Compress);
                    SetEncoding("deflate");
            }
    }

    private bool IsEncodingAccepted(string encoding)
    {
            return HttpContext.Current.Request.Headers["Accept-encoding"] != null &&
                    HttpContext.Current.Request.Headers["Accept-encoding"].Contains(encoding);
    }

    private void SetEncoding(string encoding)
    {
            HttpContext ctx = HttpContext.Current;
            string responseEncodings = ctx.Response.Headers.Get("Content-encoding");
            if (responseEncodings == null || !responseEncodings.Contains(encoding))
                    HttpContext.Current.Response.AppendHeader("Content-encoding", encoding);
    }

    public void Dispose()
    {
            Dispose(true);
    }

    private void Dispose(bool dispose)
    {
            isDisposed = dispose;
    }
}
使用系统;
使用系统IO压缩;
使用System.Web;
使用System.Web.Security;
/// 
///为SOAP API实现双向HTTP压缩
///代码取自:http://netpl.blogspot.co.uk/2009/07/aspnet-webservices-two-way-    response-and.html
///修复:在服务器上发生异常时设置Content encoding:gzip头。
///修正:当请求没有GZIPed时,不要尝试解密GZIP请求流。
/// 
公共类HttpCompressionModule:IHttpModule
{
私有bool isDisposed=false;
~HttpCompressionModule()
{
处置(虚假);
}
公共void Init(HttpApplication上下文)
{
context.BeginRequest+=新事件处理程序(context_BeginRequest);
context.PreSendRequestHeaders+=新事件处理程序(context\u PreSendRequestHeaders);
}
void context\u PreSendRequestHeaders(对象发送方,事件参数e)
{
//修复发生异常时丢失的标题。
HttpApplication app=发送方作为HttpApplication;
HttpContext ctx=app.Context;
如果(app.Response.Filter是GZipStream)设置编码(“gzip”);
如果(app.Response.Filter为DeflateStream)设置编码(“deflate”);
//固定式双割台
if(ctx.Response.Headers[“内容编码”]=“gzip,gzip”)
ctx.Response.Headers.Set(“内容编码”、“gzip”);
}
public void Context_BeginRequest(对象发送方,事件参数e)
{
HttpApplication app=发送方作为HttpApplication;
HttpContext ctx=app.Context;
//目前仅为Uploader API webservice启用
如果(!ctx.Request.Url.PathAndQuery.ToLower().包含(“uploaderapi.asmx”))
{
返回;
}
//如果请求是GZIP编码的,则添加请求筛选器
string requestEncoding=ctx.Request.Headers[“内容编码”];
if(requestEncoding!=null&&requestEncoding==“gzip”)
{
app.Request.Filter=
新系统.IO.Compression.GZipStream(app.Request.Filter,CompressionMode.decompresse);
}
//如果客户端接受压缩响应,则添加响应压缩筛选器
如果(IsEncodingAccepted(“gzip”))
{
app.Response.Filter=新的gzip流(app.Response.Filter,CompressionMode.Compress);
设置编码(“gzip”);
}
否则,如果(IsEncodingAccepted(“deflate”))
{
app.Response.Filter=新的DeflateStream(app.Response.Filter,CompressionMode.Compress);
设置编码(“deflate”);
}
}
私有布尔IsEncodingAccepted(字符串编码)
{
返回HttpContext.Current.Request.Headers[“接受编码”]!=null&&
HttpContext.Current.Request.Headers[“接受编码”]。包含(编码);
}
私有void SetEncoding(字符串编码)
{
HttpContext ctx=HttpContext.Current;
字符串responseEncodings=ctx.Response.Headers.Get(“内容编码”);
if(responseEncodings==null | |!responseEncodings.Contains(编码))
HttpContext.Current.Response.AppendHeader(“内容编码”,编码);
}
公共空间处置()
{
处置(真实);
}
私有无效处置(bool处置)
{
isDisposed=处置;
}
}

请参考这篇文章(),事实上我已经在使用这段代码了,但它有几个bug我很难修复。不过,我在这方面花了更多的时间,现在已经修复了错误。我的版本修复了以下问题:在服务器上发生异常时设置Content encoding gzip头。第二个修正:当请求没有GZIPed时,不要尝试解密GZIP请求流。我在这里发布了代码的更新版本:非常感谢原始解决方案。我将奖励你:)第三个修复方法是抑制“内容编码”头的加倍,所以它变成了“gzip,gzip”。不确定这是否真的有必要,但它是不正确的。谢谢尼克,我希望这个解决方案能像对我们一样对你有好处。实际上我现在已经删除了这个代码。即使是“f”