2015-12-13 15 views
8

私の角クライアントからAspNet Web APIへの要求を圧縮して、帯域幅の使用を最適化しようとしています。これを達成する方法はありますか?Angular to web APIからの圧縮要求

+5

この完全に有効な質問が閉じられるように投票した理由私は疑問に思う:

そして、ここでは、この努力の結果です。 –

+1

@DarinDimitrovおそらく広すぎる。いいえ、MCVEは別の可能性です。また、それは考慮されることができます(http://stackoverflow.com/questions/32246690/angularjs-compress-http-post-data) – DavidG

+1

私は質問が広すぎるとは思わない。まったく逆です。これはまさにポイントです.JavaScriptクライアントから送信されるHTTPリクエストを最適化する方法を探しています。 MCVEに関する限り、この特定のケースでは、設計の種類の問題であるため、提供されるコードや例はありません。一方、私はそれが欺瞞かもしれないことに同意します。 –

答えて

9

gzipなどのデータを圧縮するための業界標準のアルゴリズムを使用することも考えられます。それらは生の文字列に対して非常に優れた圧縮を提供し、大きなオブジェクトをサーバーに送信する場合は、要求のサイズを減らしてパフォーマンスを確実に得ることができます。限られた帯域幅を持つモバイルデバイスでアプリを実行すると得られるメリットはもちろんです。

しかし、十分なチャタリング、練習に入ることができます。ここで最大の課題は、javascriptで有効なgzipリクエストを生成することです。 1つの可能性は、この形式の仕様を読み、独自の実装をロールバックするか、既存のライブラリを使用することです。特に興味深いものはpakoです。

これは単に、次のコマンドを発行してbowerを使用して、アプリケーションにインストールするには、些細です:

bower install pako 

は、今度は、サンプル要求はクライアントの観点からどのように見えるかを見てみましょう。あなたがサーバーに次のJSONを送信したいと仮定しましょう(どちらかPOSTとして、あるいは動詞をPUT):

{ my: 'super', puper: [456, 567], awesome: 'pako' } 

あなたは、単に現代のブラウザで利用可能な無地XMLHttpRequestオブジェクトを使用して(下記の場合は読むことを達成できます

<script src="bower_components/pako/dist/pako.min.js"></script> 
<script> 
    var xhr = new XMLHttpRequest(); 
    xhr.open('POST', '/api/myresource', true); 

    // Indicate to the serve that you will be sending data in JSON format 
    xhr.setRequestHeader('Content-Type', 'application/json'); 
    // Indicate to the server that your data is encoded using the gzip format 
    xhr.setRequestHeader('Content-Encoding', 'gzip'); 

    xhr.onreadystatechange = function (e) { 
     if (this.readyState == 4 && this.status == 200) { 
      alert('We have just successfully sent a gzip encoded payload to the server'); 
     } 
    }; 

    var data = { my: 'super', puper: [456, 567], awesome: 'pako' }; 
    var binaryString = pako.gzip(JSON.stringify(data)); 
    xhr.send(binaryString); 
</script> 

、あなたが角度の要求について尋ねているので、のは、ネイティブ$httpオブジェクトを使用して、このサンプルのAJAX要求をAngularifyてみましょう:あなたは)角度特定のソリューションに興味がある

<!DOCTYPE html> 
<html> 
<head> 
    <title></title> 
    <meta charset="utf-8" /> 
</head> 
<body ng-app="myapp"> 
    <div ng-controller="HomeController"></div> 
    <script src="bower_components/pako/dist/pako.min.js"></script> 
    <script src="bower_components/angular/angular.min.js"></script> 
    <script> 
     angular.module('myapp', []).controller('HomeController', ['$http', function ($http) { 
      var data = { my: 'super', puper: [456, 567], awesome: 'pako' }; 
      var binaryString = pako.gzip(JSON.stringify(data)); 
      var req = { 
       method: 'POST', 
       url: '/api/myresource', 
       headers: { 
        'Content-Type': 'application/json', 
        'Content-Encoding': 'gzip' 
       }, 
       data: binaryString, 
       transformRequest: [] 
      } 

      $http(req).then(function (result) { 
       alert('We have just successfully sent a gzip encoded payload to the server'); 
      }, function() { 
       alert('OOPS, something went wrong, checkout the Network tab in your browser for more details'); 
      }); 
     }]); 
    </script> 
</body> 
</html> 

OK、基本的には、AJAXリクエストを使用するクライアントサイド送信部分をカバーし、適切なContent-Encodingリクエストヘッダーを指定しました。

ここでは、サーバー側の部分について説明します。 IISでホストされているWeb API 2を使用しているとしましょう。

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     var config = GlobalConfiguration.Configuration; 
     config.MapHttpAttributeRoutes(); 
     app.UseWebApi(config); 
     config.EnsureInitialized(); 
    } 
} 

、その後明らかにあなたがあなたのペイロードをマッピングするためのビューモデルがあります:

public class MyViewModel 
{ 
    public string My { get; set; } 
    public int[] Puper { get; set; } 
    public string Awesome { get; set; } 
} 

だから、基本的に、あなたのWeb APIをブートストラップしますASP.NETアプリケーションでStartupクラスを持っているでしょう

とあなたのAJAX要求のサーバー側のハンドラの目的を果たすだろうウェブAPIコントローラ:

public class TestController : ApiController 
{ 
    [HttpPost] 
    [Route("api/myresource")] 
    public HttpResponseMessage Post(MyViewModel viewModel) 
    { 
     // We will simply echo out the received request object to the response 
     var response = Request.CreateResponse(HttpStatusCode.OK, viewModel); 
     return response; 
    } 
} 

これまでのところとても良いです。残念ながら、Web APIはgzip要求エンコーディングをそのまま受け付けていません。しかし、これはかなり拡張可能なフレームワークなので、クライアントからのリクエストを解凍する方法を知るカスタム委譲ハンドラを記述するだけです。

public class DecompressedHttpContent: HttpContent 
{ 
    private readonly HttpContent _content; 
    public DecompressedHttpContent(HttpContent content) 
    { 
     _content = content; 
     foreach (var header in _content.Headers) 
     { 
      Headers.TryAddWithoutValidation(header.Key, header.Value); 
     } 
    } 

    protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) 
    { 
     using (var originalStream = await _content.ReadAsStreamAsync()) 
     using (var gzipStream = new GZipStream(originalStream, CompressionMode.Decompress)) 
     { 
      await gzipStream.CopyToAsync(stream); 
     } 
    } 

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

、その後、私たちの委譲ハンドラ:

のは、カスタムHttpContentを書くことから始めましょう

public class GzipDecompressionHandler : DelegatingHandler 
{ 
    protected override async Task<HttpResponseMessage> SendAsync(
     HttpRequestMessage request, 
     CancellationToken cancellationToken 
    ) 
    { 
     var isCompressedPayload = request.Content.Headers.ContentEncoding.Any(x => string.Equals(x, "gzip", StringComparison.InvariantCultureIgnoreCase)); 
     if (!isCompressedPayload) 
     { 
      return await base.SendAsync(request, cancellationToken); 
     } 

     request.Content = new DecompressedHttpContent(request.Content); 
     return await base.SendAsync(request, cancellationToken); 
    } 
} 

すべてのことは、私たちのStartupクラスでこのカスタムハンドラを登録するには、今されて残っています:

config.MessageHandlers.Add(new GzipDecompressionHandler()); 

それはかなりです。クライアント側のAJAXリクエストからTestController.Postアクションが呼び出されると、入力ボディに適切なヘッダーが含まれ、委任ハンドラがデコード処理を行い、Postアクションが呼び出されたときに期待されるビューモデルが既にデシリアライズされるようにします。

ここで要約されているような小さな要求に対しては、gzipを使用してもほとんど得られないことに注意してください。追加する魔法のgzip番号のために悪化さえする可能性もありますペイロード。しかし、より大きなリクエストに対しては、このアプローチは確実にリクエストサイズを減らし、gzipの使用を強くお勧めします。

enter image description here

関連する問題