簡體   English   中英

Azure應用服務-請求中的GZip壓縮

[英]Azure App Service- GZip Compression in Request

使用此代碼(沒有請求壓縮部分),我可以從Azure App Service(具有脫機同步的Xamarin.Froms App)獲得gzip壓縮的內容。 但是,當我嘗試gzip請求http-content時,會收到“錯誤請求”。

有任何想法嗎? 是否可以使用Azure App Service gzip請求內容?

namespace XXX.XXX.XXX.XXX.XXX
{
    public class HttpGZipClientHandler : System.Net.Http.HttpClientHandler
    {
        long time = 0;
        private long _downloadedBytesFromServer;
        private long _downloadedProcessedBytes;
        private long _intendedUploadedBytesToServer;
        private long _uploadedBytesToServer;
        private long _additionalTimeOverhead = 0;

        public override bool SupportsAutomaticDecompression { get { return true; } }
        public long DownloadedBytesFromServer { get { return _downloadedBytesFromServer; } }
        public long DownloadedProcessedBytes { get { return _downloadedProcessedBytes; } }
        public long IntendedUploadedBytesToServer { get { return _intendedUploadedBytesToServer; } }
        public long UploadedBytesToServer { get { return _uploadedBytesToServer; } }
        public long AdditionalTimeOverhead { get { return _additionalTimeOverhead; } }

        public void ResetStatistics()
        {
            _downloadedBytesFromServer = 0;
            _downloadedProcessedBytes = 0;
            _intendedUploadedBytesToServer = 0;
            _uploadedBytesToServer = 0;
            _additionalTimeOverhead = 0;
        }

        protected override async Task<System.Net.Http.HttpResponseMessage> SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {

            //Save content headers before compressing
            System.Collections.Generic.Dictionary<string, System.Collections.Generic.IEnumerable<string>> savedContentHeaders = new Dictionary<string, IEnumerable<string>>();
            foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.IEnumerable<string>> keyValue in request.Content.Headers)
            {
                savedContentHeaders.Add(keyValue.Key, keyValue.Value);
            }

            //Compress request content
            System.Diagnostics.Stopwatch sp1 = new System.Diagnostics.Stopwatch();
            sp1.Start();

            _intendedUploadedBytesToServer += request.Content.Headers.ContentLength.HasValue ? request.Content.Headers.ContentLength.Value : 0;

            await request.Content.LoadIntoBufferAsync().ConfigureAwait(false);
            request.Content = new HttpGZipContent(await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false), System.IO.Compression.CompressionMode.Compress);

            byte[] uploadedBytes = await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
            _uploadedBytesToServer += uploadedBytes.Length;

            sp1.Stop();
            _additionalTimeOverhead += sp1.ElapsedMilliseconds;

            //Set headers
            foreach (System.Collections.Generic.KeyValuePair<string, System.Collections.Generic.IEnumerable<string>> keyValue in savedContentHeaders)
            {
                request.Content.Headers.Add(keyValue.Key, keyValue.Value);
            }

            request.Headers.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip"));
            request.Content.Headers.Add("Content-Encoding", "gzip");

            //Execute request
            System.Net.Http.HttpResponseMessage response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
            _downloadedBytesFromServer += response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : 0;

            //Decompress response content
            if (response.Content.Headers.ContentEncoding.Contains("gzip"))
            {
                System.Diagnostics.Stopwatch sp2 = new System.Diagnostics.Stopwatch();
                sp2.Start();

                await response.Content.LoadIntoBufferAsync().ConfigureAwait(false);
                response.Content = new HttpGZipContent(await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false), System.IO.Compression.CompressionMode.Decompress);

                byte[] processedBytes = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
                _downloadedProcessedBytes += processedBytes.Length;

                sp2.Stop();
                _additionalTimeOverhead += sp2.ElapsedMilliseconds;
            }
            else
                _downloadedProcessedBytes += response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : 0;

            return response;
        }
    }

    internal sealed class HttpGZipContent : System.Net.Http.HttpContent
    {
        private readonly byte[] _content;
        private readonly System.IO.Compression.CompressionMode _compressionMode;

        public HttpGZipContent(byte[] content, System.IO.Compression.CompressionMode compressionMode)
        {
            _compressionMode = compressionMode;
            _content = content;
        }

        protected override async System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context)
        {
            if (_compressionMode == System.IO.Compression.CompressionMode.Compress)
            {
                using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(_content.Length))
                {
                    using (System.IO.Compression.GZipStream zipStream = new System.IO.Compression.GZipStream(memoryStream, System.IO.Compression.CompressionMode.Compress))
                    {
                        zipStream.Write(_content, 0, _content.Length);
                        zipStream.Flush();
                    }

                    byte[] compressed = memoryStream.ToArray();
                    System.IO.MemoryStream copyStream = new System.IO.MemoryStream(compressed);
                    await copyStream.CopyToAsync(stream).ConfigureAwait(false);
                }
            }
            else
            {
                using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(_content, 0, _content.Length))
                {
                    using (System.IO.Compression.GZipStream zipStream = new System.IO.Compression.GZipStream(memoryStream, System.IO.Compression.CompressionMode.Decompress))
                    {
                        await zipStream.CopyToAsync(stream).ConfigureAwait(false);
                    }
                }
            }
        }

        protected override bool TryComputeLength(out long length)
        {
            length = _content.Length;
            return true;
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }
    }
}

根據我的理解,您需要為移動應用程序后端實現請求解壓縮。 如果使用的是C#后端,則可以如下創建自定義ActionFilterAttribute

public class RequestDeCompressFilter : ActionFilterAttribute
{
    public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken)
    {
        var request = actionContext.Request;
        if (request.Content.Headers.ContentEncoding.Contains("GZIP"))
        {
            await request.Content.LoadIntoBufferAsync().ConfigureAwait(false);
            request.Content = new HttpGZipContent(await request.Content.ReadAsByteArrayAsync().ConfigureAwait(false), System.IO.Compression.CompressionMode.Decompress);
        }
       //TODO: compress the response, you could follow http://www.intstrings.com/ramivemula/articles/jumpstart-47-gzipdeflate-compression-in-asp-net-mvc-application/
       await base.OnActionExecutingAsync(actionContext, cancellationToken);
    }

    public override Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
    {   
        //you could also compress the response here
        return base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
    }
}

然后,標記您的操作,如下所示:

[RequestDeCompressFilter]
public async Task<IHttpActionResult> PostMessage(Message item)

另外,您可以遵循ASP.NET Web API中的HTTP消息處理程序來實現HTTP消息處理程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM