Sending json as Gzip in https in xamarin.forms for

2019-01-27 09:07发布

问题:

I am sending an rest API request to my server in HTTPS, and gets a json response, in my xamarin.forms android (OS is marshmallow).

Is the json response automatically compressed from the server to my client, or do i need to define something in my HttpClient class, in the android, in order for it to be compressed (i have bad internet so the compression is important to me...)

回答1:

Decompression:

In order to consume compressed JSON using HttpClient in Xamarin.Forms you have to create a HttpClientHandler this way:

var httpHandler = new HttpClientHandler
{
    AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate
};
httpClient = new HttpClient(httpHandler);
await httpClient.GetStringAsync(url);

Alternatively you can use ModernHttpClient which supports decompression out of the box according to this thread.

Compression:

To enable compression in Xamarin.Forms you need to compress the request content yourself. For this let's extend HttpContent:

public class JsonContent : HttpContent
    {
        private JsonSerializer serializer { get; }
        private object value { get; }

        public JsonContent(object value)
        {
            this.serializer = new JsonSerializer();
            this.value = value;
            Headers.ContentType = new MediaTypeHeaderValue("application/json");
            Headers.ContentEncoding.Add("gzip");
        }

        protected override bool TryComputeLength(out long length)
        {
            length = -1;
            return false;
        }

        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            return Task.Factory.StartNew(() =>
            {
                using (var gzip = new GZipStream(stream, CompressionMode.Compress, true))
                using (var writer = new StreamWriter(gzip))
                {
                    serializer.Serialize(writer, value);
                }
            });
        }
    }

Now we can wrap our content with JsonContent and it will be sent compressed to our backend:

var jsonContent = new JsonContent(new List<string> { "a", "b", "c", "d", "e", "f" });
await httpClient.PostAsync(url, jsonContent));

Backend:

From your question I also understand that you are not sure if your 'server' is compressing the response. It should be very easy to check, check if your response contains Content-Encoding: gzip header.

P.S.: I created a sample project on github that contains a .NET Core MVC backend with GZip compression / decompression support and Xamarin.Forms iOS frontend which consumes and sends compressed data (using GZip) with both HttpClient and ModernHttpClient.

Screens attached: