HttpClient与APS.NET Web API:请求内容的压缩与解压
2016-09-14 17:05
375 查看
HttpClient与APS.NET Web API:请求内容的压缩与解压
首先说明一下,这里的压缩与解压不是通常所说的http compression——那是响应内容在服务端压缩、在客户端解压,而这里是请求内容在客户端压缩、在服务端解压。对于响应内容的压缩,一般Web服务器(比如IIS)都提供了内置支持,只需在请求头中包含 Accept-Encoding: gzip, deflate ,客户端浏览器与HttpClient都提供了内置的解压支持。HttpClient中启用这个压缩的代码如下:
var httpClient = new HttpClient(new HttpClientHandler { AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate });
对于请求内容的压缩,.NET中的HttpClient并没有提供内置支持,IIS也没有提供对解压的内置支持,需要自己写代码实现,本文也是由此而生。
为什么要对请求内容进行压缩呢?目前我们在2种应用场景下遇到:1)用HttpClient调用第三方Web API;2)或者iOS App调用自己的Web API时需要提交大文本数据。
对于压缩与解压,System.IO.Compression中提供了对应的类库——GZipStream与DeflateStream,我们只需要在HttpClient与Web API中应用它们即可。
先来看看客户端HttpClient的实现。我们需要实现一个支持压缩的HttpContent——CompressedContent,实现代码如下:
public enum CompressionMethod { GZip = 1, Deflate = 2 } public class CompressedContent : HttpContent { private readonly HttpContent _originalContent; private readonly CompressionMethod _compressionMethod; public CompressedContent(HttpContent content, CompressionMethod compressionMethod) { if (content == null) { throw new ArgumentNullException("content"); } _originalContent = content; _compressionMethod = compressionMethod; foreach (KeyValuePair<string, IEnumerable<string>> header in _originalContent.Headers) { Headers.TryAddWithoutValidation(header.Key, header.Value); } Headers.ContentEncoding.Add(_compressionMethod.ToString().ToLowerInvariant()); } protected override bool TryComputeLength(out long length) { length = -1; return false; } protected async override Task SerializeToStreamAsync(Stream stream, TransportContext context) { if (_compressionMethod == CompressionMethod.GZip) { using (var gzipStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: true)) { await _originalContent.CopyToAsync(gzipStream); } } else if (_compressionMethod == CompressionMethod.Deflate) { using (var deflateStream = new DeflateStream(stream, CompressionMode.Compress, leaveOpen: true)) { await _originalContent.CopyToAsync(deflateStream); } } } }
主要就是重载HttpContent.SerializeToStreamAsync()方法,在其中使用相应的压缩算法进行压缩。
HttpClient使用这个CompressedContent的方法如下:
var json = JsonConvert.SerializeObject(bookmark); var content = new CompressedContent( new StringContent(json, Encoding.UTF8, "application/json"), CompressionMethod.GZip); var response = await _httpClient.PostAsync("/api/bookmarks", content);
再来看看服务端ASP.NET Web API中的实现,需要实现一个DelegatingHandler——DecompressionHandler:
public class DecompressionHandler : DelegatingHandler { protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (request.Method == HttpMethod.Post) { bool isGzip = request.Content.Headers.ContentEncoding.Contains("gzip"); bool isDeflate = !isGzip && request.Content.Headers.ContentEncoding.Contains("deflate"); if (isGzip || isDeflate) { Stream decompressedStream = new MemoryStream(); if (isGzip) { using (var gzipStream = new GZipStream(await request.Content.ReadAsStreamAsync(), CompressionMode.Decompress)) { await gzipStream.CopyToAsync(decompressedStream); } } else if (isDeflate) { using (var gzipStream = new DeflateStream(await request.Content.ReadAsStreamAsync(), CompressionMode.Decompress)) { await gzipStream.CopyToAsync(decompressedStream); } } decompressedStream.Seek(0, SeekOrigin.Begin); var originContent = request.Content; request.Content = new StreamContent(decompressedStream); foreach (var header in originContent.Headers) { request.Content.Headers.Add(header.Key, header.Value); } } } return await base.SendAsync(request, cancellationToken); } }
重载DelegatingHandler.SendAsync()方法,在其中用GZipStream或DeflateStream完成解压操作。
然后在WebApiConfig中应用这个DecompressionHandler,代码如下:
public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new DecompressionHandler()); } }
最后用这个支持请求内容压缩的HttpClient调用一下这个支持请求内容解压的Web API测试一下,用WireShark抓包看一下压缩是否生效。
测试成功!
相关文章推荐
- HttpClient与APS.NET Web API:请求内容的压缩与解压
- http client对post内容gzip压缩和server端解压接收
- Asp.net使用HttpModule压缩并删除空白Html请求
- Asp.net使用HttpModule压缩并删除空白Html请求
- HttpClient 通过域名访问请求接口出现java.net.UnknownHostException解决方法
- 通过HttpClient 调用ASP.NET Web API
- Asp.Net Web API 2第四课——HttpClient消息处理器
- HttpClient + ASP.NET Web API, WCF之外的另一个选择
- HttpClient + ASP.NET Web API(附加WebClient HttpWebRequest JQuery AJAX请求方式)
- HttpClient 通过域名访问请求接口出现java.net.UnknownHostException解决方法
- IIS7.5配置Asp.net项目出现HTTP 错误 404.17 - Not Found 请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。
- httpclient发起https请求以及获取https返回内容
- ASP.NET MVC Web API 学习笔记----HttpClient简介
- Asp.Net Web API 2第四课——HttpClient消息处理器
- HttpClient发送请求后得到的响应内容出现部分乱码的问题
- Asp.net使用HttpModule压缩并删除空白Html请求
- 【ASP.NET Web API教程】3.4 HttpClient消息处理器
- Asp.Net Web API 2第四课——HttpClient消息处理器
- HttpClient + ASP.NET Web API, WCF之外的另一个选择
- Web Api 请求调用——httpclient