First of all, the compression and decompression here is not the usual HTTP compression--that is the response content on the server compression, decompression on the client, and here is the request content in the client compression, decompression on the server.
For compression of the response content, the general Web server (such as IIS) provides built-in support that includes accept-encoding:gzip in the request header, deflate , and the client browser and HttpClient provide built-in decompression support. The code for enabling this compression in HttpClient is as follows:
var New HttpClient (new httpclienthandler {automaticdecompression = | System.Net.DecompressionMethods.Deflate});
For compression of the requested content. NET HttpClient does not provide built-in support, IIS also does not provide the built-in support for decompression, need to write code implementation, this article is born.
Why compress the content of the request? Currently we encounter in 2 scenarios: 1) You need to submit large text data when calling a third-party web api;2 with HttpClient or iOS app calling your own web API.
For compression and decompression, the corresponding class library--gzipstream and Deflatestream are available in System.IO.Compression, and we only need to apply them in the HttpClient and Web APIs.
Let's take a look at the implementation of client httpclient. We need to implement a httpcontent--compressedcontent that supports compression, the implementation code is as follows:
Public enumcompressionmethod{GZip=1, Deflate=2} Public classcompressedcontent:httpcontent{Private ReadOnlyhttpcontent _originalcontent; Private ReadOnlyCompressionmethod _compressionmethod; Publiccompressedcontent (httpcontent content, Compressionmethod compressionmethod) {if(Content = =NULL) { Throw NewArgumentNullException ("content"); } _originalcontent=content; _compressionmethod=Compressionmethod; foreach(keyvaluepair<string, ienumerable<string>> Headerinch_originalcontent.headers) {headers.tryaddwithoutvalidation (header). Key, header. Value); } Headers.ContentEncoding.Add (_compressionmethod.tostring (). Tolowerinvariant ()); } protected Override BOOLTrycomputelength ( out Longlength) {Length= -1; return false; } protected Async OverrideTask Serializetostreamasync (Stream stream, TransportContext context) {if(_compressionmethod = =compressionmethod.gzip) {using(varGZipStream =NewGZipStream (Stream, compressionmode.compress, Leaveopen:true)) { await_originalcontent.copytoasync (GZipStream); } } Else if(_compressionmethod = =compressionmethod.deflate) {using(varDeflatestream =NewDeflatestream (Stream, compressionmode.compress, Leaveopen:true)) { await_originalcontent.copytoasync (Deflatestream); } } }}
The main thing is the overloaded Httpcontent.serializetostreamasync () method, in which compression is used with the appropriate compression algorithm.
HttpClient Use this compressedcontent method as follows:
var json = jsonconvert.serializeobject (bookmark); var New compressedcontent ( new"application/json"), Compressionmethod.gzip); var await _httpclient.postasync ("/api/bookmarks", content);
Take a look at the implementation in the server-side ASP. NET Web API, you need to implement a delegatinghandler--decompressionhandler:
Public classdecompressionhandler:delegatinghandler{protected Override AsyncTaskSendAsync (httprequestmessage request, CancellationToken CancellationToken) {if(Request. Method = =httpmethod.post) {BOOLIsgzip = Request. Content.Headers.ContentEncoding.Contains ("gzip"); BOOLIsdeflate =!isgzip && request. Content.Headers.ContentEncoding.Contains ("deflate"); if(Isgzip | |isdeflate) {Stream Decompressedstream=NewMemoryStream (); if(isgzip) {using(varGZipStream =NewGZipStream (awaitrequest. Content.readasstreamasync (), compressionmode.decompress)) { awaitGzipstream.copytoasync (Decompressedstream); } } Else if(isdeflate) {using(varGZipStream =NewDeflatestream (awaitrequest. Content.readasstreamasync (), compressionmode.decompress)) { awaitGzipstream.copytoasync (Decompressedstream); }} decompressedstream.seek (0, Seekorigin.begin); varOrigincontent =request. Content; Request. Content=Newstreamcontent (Decompressedstream); foreach(varHeaderinchorigincontent.headers) {request. CONTENT.HEADERS.ADD (header. Key, header. Value); } } } return await Base. SendAsync (Request, CancellationToken); }}
Overloads the Delegatinghandler.sendasync () method, in which the decompression operation is done with GZipStream or deflatestream.
Then apply this decompressionhandler in Webapiconfig, with the following code:
Public Static class webapiconfig{ publicstaticvoid Register (httpconfiguration config) { config. Messagehandlers.add (new Decompressionhandler ());} }
Finally, with this support request content compression HttpClient call this support request content decompression of the Web API test, with Wireshark to see if compression is effective.
Test success!
Resources
How to compress HTTP request on the fly and without loading compressed buffer in memory
How does enable a. Net Web-api to accept g-ziped posts
HTTP Message Handlers in ASP Web API
Compressed HTTP Requests
HttpClient and Aps.net Web API: Compression and decompression of request content