2016-09-02 17 views
0

イメージを取り込んでイメージのサイズを変更してから、100x100イメージのパスをユーザーに返すアップロード機能があります。 私の場合、ユーザーはすべてのサイズ変更とアップロードが完了するまで待つつもりですが、明らかにユーザーエクスペリエンスには不利です。 私はActionResultを非同期タスクとして作ろうとしましたが、問題が発生しました。 これは私のコードです。すべてのアップロードが完了するまで待ちます。WebAPI返信条件付きと非同期

[HttpPost] 
    [Route("UploadProfileImage")] 
    public async Task<IHttpActionResult> UploadProfileImage() 
    { 
     string userId= Identifier.GetIdentifier(); 
     ReturnResult response = new ReturnResult(); 
     try 
     { 

      var provider = new MultipartMemoryStreamProvider(); 
      await Request.Content.ReadAsMultipartAsync(provider); 
      var fileNameParam = provider.Contents[0].Headers.ContentDisposition.Parameters.FirstOrDefault(p => p.Name.ToLower() == "filename"); 
      string fileName = (fileNameParam == null) ? "" : fileNameParam.Value.Trim('"'); 
      byte[] file = await provider.Contents[0].ReadAsByteArrayAsync(); 
      MemoryStream imgStream = new MemoryStream(file); 
      Bitmap mg = new Bitmap(imgStream); 
      List<Size> sizes = new List<Size>(); 
      sizes.Add(new Size { Width = mg.Width, Height = mg.Height }); 
      sizes.Add(new Size { Width = 100, Height = 100 }); 
      sizes.Add(new Size { Width = 300, Height = 300 }); 
      sizes.Add(new Size { Width = 500, Height = 500 }); 
      sizes.Add(new Size { Width = 800, Height = 800 }); 
      int index = 0; 
      foreach (var size in sizes) 
      { 

       byte[] newImageByteArray = Helpers.CreateImageThumbnail(file, Convert.ToInt32(size.Width), Convert.ToInt32(size.Height)); 
       Helpers.SaveProfileImage(newImageByteArray, agentId, size, index == 0 ? true : false); 
       index++; 
       //---*--->>Here I Should check here that if original & 100x100 image were uploaded then return a response and continue uploading the others (if(index>1)) 
      } 
      var path = "https://stackoverflow.com/users/uploads/100/" + userId+ ".jpg" + "?v=" + Guid.NewGuid(); 


      UserManager.UpdateUploadImage(userId, path); 
      response.ReturnObject = path; 
      response.ReturnCode = ReturnCodes.Success; 
      return Ok(response); 
     } 
     catch (Exception ex) 
     { 
      response.ReturnObject = ex; 
      response.ReturnCode = ReturnCodes.Exception; 
      return Ok(response); 
     } 

注:クライアントはwebapiサーバーに投稿するangularJSアプリです。 これを達成するためにコードを書き換える方法はありますか?

+0

サイドノート:私はあなたの "ユーザー"がクライアントサイドのアプリだと思う - この場合、サーバーサイドコードを同期から非同期に変更すると、サーバーコールが非同期であるため、クライアントコードの動作に影響しません。それを明確にするために[編集]する必要があるかどうか検討してください。 –

+0

ユーザーはanglejsのアプリ – Basilf

+0

そう思った。サーバー側のコードを書き換えるだけでは問題は解決しません(一部の作業を並列化して待ち時間を短縮できますが、完全に削除することはできません)。参照してください –

答えて

3

私のActionResultを非同期タスクとして作成しようとしましたが、問題が発生しました。

async doesn't change the HTTP protocol(私のブログで説明しているように)から、これは正しい解決策ではありません。

は、100x100イメージのパスをユーザーに返します。これは正しい解決策ではありません。

はどのようにウェブ要求は、ユーザへの応答を返しますし、後で(パスを返すために)再びを返しますか?これはHTTPのような要求/応答プロトコルでは不可能です。リクエストごとに1つの応答しか得られません。

私の場合、ユーザーはすべてのサイズ変更とアップロードが完了するまで待つつもりですが、明らかにユーザーエクスペリエンスには不利です。

次のオプションがあります。HTTPリクエストの作業の独立を追跡する複雑な溶液中に入れ

  1. (これは通常Azureキューのような信頼性の高いキューは、Azureの機能のような独立した労働者のサービスに接続されている必要があり)、そして事前にUIに通知するための手段を提供してください(実際にはポーリングが実際より優れている場合は、SignalRはこれに適しています。
  2. クライアント側でAJAXを使用します。あなたは既に(2)をやっている

注:

クライアントはangularJSアプリであるWEBAPIサーバーへのポスト。

だから、あなたがしなければならないすべては、それは、ユーザが他の事をする許可する前に要求を待たないようにクライアントを変更です。サーバーの変更は必要ありません。

関連する問題