原文:http://blogs.msdn.com/b/kiranchalla/archive/2012/09/04/handling-compression-accept-encoding-sample.aspx
ps:此人博客非常不错,可以收藏下http://blogs.msdn.com/b/kiranchalla/
Long time back there was a question on forums regarding how we could achieve compression scenario via Accept-Encoding headers in Web API. Thought of bringing that sample here so that it could be useful for anyone looking for this kind of functionality.
NOTE: ASP.NET Web API doesn’t have inherent support for Accept-Encoding header.
Let’s assume we have the following controller which is returning 3 different HttpContents: StringContent, StreamContent & ObjectContent.
public class AcceptEncodingTestsController : ApiController { [HttpGet] public HttpResponseMessage GetStringContent() { HttpResponseMessage response = new HttpResponseMessage(); response.Content = new StringContent("Hello World!"); return response; } [HttpGet] public HttpResponseMessage GetStreamContent() { HttpResponseMessage response = new HttpResponseMessage(); response.Content = new StreamContent(new FileStream(@"D\Sample.txt", FileMode.Open)); response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain"); return response; } [HttpGet] public Customer GetCustomer() // the return value is actually converted to ObjectContent { return new Customer() { Id = 100, DateOfBirth = new DateTime(1975, 4, 3) }; } }Encoding handler :
public class EncodingDelegateHandler : DelegatingHandler { protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) => { HttpResponseMessage response = responseToCompleteTask.Result; if (response.RequestMessage.Headers.AcceptEncoding != null && response.RequestMessage.Headers.AcceptEncoding.Count > 0) { string encodingType = response.RequestMessage.Headers.AcceptEncoding.First().Value; response.Content = new CompressedContent(response.Content, encodingType); } return response; }, TaskContinuationOptions.OnlyOnRanToCompletion); } } public class CompressedContent : HttpContent { private HttpContent originalContent; private string encodingType; public CompressedContent(HttpContent content, string encodingType) { if (content == null) { throw new ArgumentNullException("content"); } if (encodingType == null) { throw new ArgumentNullException("encodingType"); } originalContent = content; this.encodingType = encodingType.ToLowerInvariant(); if (this.encodingType != "gzip" && this.encodingType != "deflate") { throw new InvalidOperationException(string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", this.encodingType)); } // copy the headers from the original content foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers) { this.Headers.TryAddWithoutValidation(header.Key, header.Value); } this.Headers.ContentEncoding.Add(encodingType); } protected override bool TryComputeLength(out long length) { length = -1; return false; } protected override Task SerializeToStreamAsync(Stream stream, TransportContext context) { Stream compressedStream = null; if (encodingType == "gzip") { compressedStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: true); } else if (encodingType == "deflate") { compressedStream = new DeflateStream(stream, CompressionMode.Compress, leaveOpen: true); } return originalContent.CopyToAsync(compressedStream).ContinueWith(tsk => { if (compressedStream != null) { compressedStream.Dispose(); } }); } }Register the handler:
config.MessageHandlers.Add(new EncodingDelegateHandler());With the above example you should see that all the 3 types of contents are compressed via the encoding handler.