ASP.NET WebAPI提供了一种简单的方式来实现GZip压缩。下面是一个示例代码,展示了如何在WebAPI中启用GZip压缩。
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));
}
public class ServerCompressionHandler : DelegatingHandler
{
private readonly ICompressor _gzipCompressor;
private readonly ICompressor _deflateCompressor;
public ServerCompressionHandler(ICompressor gzipCompressor, ICompressor deflateCompressor)
{
_gzipCompressor = gzipCompressor;
_deflateCompressor = deflateCompressor;
}
protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await base.SendAsync(request, cancellationToken);
if (response.Content != null)
{
if (IsCompressableContent(response))
{
string encodingType = GetEncodingType(request);
if (encodingType.Equals("gzip", StringComparison.OrdinalIgnoreCase))
{
response.Content = new CompressedContent(response.Content, _gzipCompressor);
response.Content.Headers.Remove("Content-Type");
response.Content.Headers.Add("Content-Encoding", "gzip");
}
else if (encodingType.Equals("deflate", StringComparison.OrdinalIgnoreCase))
{
response.Content = new CompressedContent(response.Content, _deflateCompressor);
response.Content.Headers.Remove("Content-Type");
response.Content.Headers.Add("Content-Encoding", "deflate");
}
}
}
return response;
}
private bool IsCompressableContent(HttpResponseMessage response)
{
if (response.Content == null || response.Content.Headers.ContentEncoding != null)
{
return false;
}
MediaTypeHeaderValue contentType = response.Content.Headers.ContentType;
if (contentType == null)
{
return false;
}
string mediaType = contentType.MediaType;
return mediaType.Equals("text/plain", StringComparison.OrdinalIgnoreCase)
|| mediaType.Equals("text/html", StringComparison.OrdinalIgnoreCase)
|| mediaType.Equals("text/xml", StringComparison.OrdinalIgnoreCase)
|| mediaType.Equals("application/xml", StringComparison.OrdinalIgnoreCase)
|| mediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase)
|| mediaType.Equals("application/xhtml+xml", StringComparison.OrdinalIgnoreCase);
}
private string GetEncodingType(HttpRequestMessage request)
{
string encodingType = null;
if (request.Headers.AcceptEncoding != null)
{
encodingType = request.Headers.AcceptEncoding
.Select(a => a.Value.ToLower())
.FirstOrDefault(s => s == "gzip" || s == "deflate");
}
return encodingType;
}
}
public class CompressedContent : HttpContent
{
private readonly HttpContent _originalContent;
private readonly ICompressor _compressor;
public CompressedContent(HttpContent content, ICompressor compressor)
{
_originalContent = content;
_compressor = compressor;
foreach (KeyValuePair> header in _originalContent.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.ContentEncoding.Add(compressor.EncodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
using (Stream compressedStream = _compressor.Compress(stream))
{
await _originalContent.CopyToAsync(compressedStream);
}
}
}
public interface ICompressor
{
string EncodingType { get; }
Stream Compress(Stream stream);
}
public class GZipCompressor : ICompressor
{
public string EncodingType
{
get { return "gzip"; }
}
public Stream Compress(Stream stream)
{
return new GZipStream(stream, CompressionMode.Compress);
}
}
public class DeflateCompressor : ICompressor
{
public string EncodingType
{
get { return "deflate"; }
}
public Stream Compress(Stream stream)
{
return new DeflateStream