6

ASP.NET MVC 4を使用して、最大30MBのサイズのビデオアップロードを受け入れています。ビデオがサイトにアップロードされると、ビデオはHttpWebRequestを使用してサードパーティのWebサービスに投稿されます。このサードパーティサービスへのアップロードは、私のサイトがブラウザに応答を返す前に、完了して応答を返す必要があります。Rackspace Cloudサイトでは、ロードバランサーのタイムアウトは30秒です。ロードバランサーを介してサイトから30秒間応答が返されない場合、ロードバランサーはブラウザにタイムアウトエラーを返し、リクエストは終了します。

したがって、ロードバランサーがタイムアウトしないように、サイトがサードパーティシステムにビデオを送信している間、サイトはブラウザーにデータを返送して接続を維持する必要があると言われています。このタスクをどのように達成しますか?

私は2つのことを探しています-アップロードが行われている間にデータとしてブラウザに何を送り返しますか?私の実際の応答はJSONなので、最後に通常のJSON応答を維持できれば、それが理想的です。

そして最後に、キープアライブデータを同時に送信しながら、サードパーティへのHttpWebRequestアップロードを実行するにはどうすればよいですか?

-

参考までに、これはラックスペースクラウドのロードバランサー接続タイムアウトドキュメントです:http ://www.rackspace.com/knowledge_center/article/connection-timed-out-error-message-1

彼らはこの問題の具体的な解決策を提供していません。

4

2 に答える 2

4

これが私の問題を解決した方法です。このソリューションは、不当なタイムアウトのあるロードバランサーを使用するすべての.netホスティングに適用できるはずです。Rackspace Cloud Sitesでは、ロードバランサーで30秒のタイムアウトが発生します。AmazonとAzureのタイムアウトは長くなりますが、長時間実行する操作がある場合は、これが有用なソリューションになる可能性があります。

asp.net mvc 4では、AsyncControllerから継承するようにコントローラーを変更できます。これにより、非同期タスクをスピンオフして、それらの完了を待つことができます。このソリューションは、ロードバランサーがアクティビティを検出してタイムアウトしないように、10秒ごとにasp.net応答を介してデータを送り返す「キープアライブ」タスクを作成します。このタスクは、uploadFinished変数がtrueに設定されていることを確認するまで実行されます。

もう1つのタスクは、長時間実行されるアップロード、またはasp.netmvcコントローラーが処理しているWeb要求を終了する前に完了する必要のあるタスクを実行します。長時間実行操作が完了すると、uploadFinished変数がtrueに設定されます。

最後に、実際のjson応答の周りにコンテナーjsonオブジェクトを手動で構築しているので、「キープアライブ」データをブラウザーに返送される有効なjsonの一部にすることができます。少し醜いハックですが、うまくいきます!

using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace MvcApplication4.Controllers
{
    public class ExampleController : AsyncController
    {

        [HttpPost]
        public string Upload(UploadModel model, HttpPostedFileBase videoFile)
        {
            // when using jquery ajax form for upload
            // IE requires text/plain content type
            // otherwise it will try to open the response as a file
            // instead of pass the response back to your javascript
            if (Request.AcceptTypes.Contains("application/json"))
            {
                Response.ContentType = "application/json";
            }
            else
            {
                Response.ContentType = "text/plain";
            }

            // start json object
            Response.Write("{\"keepalive\":\"");
            Response.Flush();

            Task[] tasks = new Task[2];
            tasks[0] = Task.Factory.StartNew(() => DoKeepAlive());
            tasks[1] = Task.Factory.StartNew(() => DoUpload(model, videoFile));
            Task.WaitAll(tasks);

            // end keepalive json property
            Response.Write("\",\"data\":");

            // insert actual response data
            JavaScriptSerializer json = new JavaScriptSerializer();
            Response.Write(json.Serialize(uploadResponse));

            // end json object
            Response.Write("}");

            return "";
        }

        public bool uploadFinished = false;
        public UploadResponseModel uploadResponse = null;

        public void DoUpload(UploadModel model, HttpPostedFileBase videoFile)
        {
            // do upload to 3rd party
            MyServiceClient c = new MyServiceClient();
            uploadResponse = c.UploadVideo(model, videoFile);
            uploadFinished = true;
        }

        public void DoKeepAlive()
        {
            // send . every 10 seconds
            while (!uploadFinished)
            {
                Response.Write(".");
                Response.Flush();
                Thread.Sleep(10000);
            }
        }
    }
}

このソリューションは、非同期処理を行うために.Net4に依存しています。.Net 4.5を使用している場合、AsyncControllerクラスに依存しないMVCコントローラーで非同期を実行する新しい方法があります。

このサイトは役に立ち、さまざまなバージョンの.NetFrameworkのasp.netmvcで非同期操作を実行する方法を説明しています。

http://dotnet.dzone.com/news/net-zone-evolution

于 2012-10-10T15:07:46.443 に答える
1

残念ながら、サイトのロードバランサー構成を調整できません。

javascriptのキープアライブを実行したいと思います。

例えば:

(function poll(){
$.ajax({ url: "server", success: function(data){
    //Update your dashboard gauge
    salesGauge.setValue(data.value);

}, dataType: "json", complete: poll, timeout: 30000 });
})();

参照:

関連する質問

jQueryの例

于 2012-10-08T19:49:47.727 に答える