如何为上传到 .NET WebService(SOAP,而不是 WCF)的 POST 数据启用压缩?我认为在 IIS 中启用动态压缩将是一件简单的事情,但启用后,它只是压缩响应,而不是 POST请求。
我已将其添加为服务参考,但在生成的 SOAPClient 上找不到任何设置来启用请求压缩。
看来我可能缺少客户端的配置设置或代码来压缩请求,然后再将其发送到服务器?或者甚至不支持我正在尝试做的事情(GZipping POST 数据)?
更多信息:我在客户端和服务器上使用 .NET 4.0。
如何为上传到 .NET WebService(SOAP,而不是 WCF)的 POST 数据启用压缩?我认为在 IIS 中启用动态压缩将是一件简单的事情,但启用后,它只是压缩响应,而不是 POST请求。
我已将其添加为服务参考,但在生成的 SOAPClient 上找不到任何设置来启用请求压缩。
看来我可能缺少客户端的配置设置或代码来压缩请求,然后再将其发送到服务器?或者甚至不支持我正在尝试做的事情(GZipping POST 数据)?
更多信息:我在客户端和服务器上使用 .NET 4.0。
4年前我在博客上写过
http://netpl.blogspot.com/2009/07/aspnet-webservices-two-way-response-and.html
我想知道你为什么没有通过谷歌搜索找到这个。无论如何,这应该适合你,我们已经在生产环境中工作了 4 年。
最后,我使用了 Wiktor Zychla 的答案,但遇到了一些错误(在他的文章的评论中也提到了)。为了完整起见,我将在此处发布我的 HttpCompression 模块的固定版本,但您需要的其余代码(和实施指南)在Wiktor 的文章中。
更新:
实际上,我不得不停止使用此代码,因为它有一个我无法修复的错误(即使使用下面的改进版本)。对于代理服务器背后的许多人来说,它会出现一个错误,上面写着“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;
}
}