私はJasonのコメントに続き、別のajax呼び出しを使用してポーリングを行い、断続的な応答を得ることができました。
以下のコードでは、サーバーにjquery.formプラグインを使用してファイルをアップロードし、コントローラレベルで長時間実行されるタスクを実行しようとしています。進行状況をユーザーに示すために、ポーリングの概念を使用して長時間実行されているタスクの状態を確認します。ここで
は、
ASPコードです。NET HTML:
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<div class="row">
<div class="col-xs-12">
<div class="alert alert-warning">This page uses jquery.form plugin to upload</div>
</div>
</div>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="NoFormContentPlaceHolder" runat="server">
<div class="row">
<div class="col-xs-12">
<form id="ImportFileForm" method="post" action="api/FileUpload/Upload" enctype="multipart/form-data">
<div class="col-xs-3">
<input type="file" id="ImportFile" name="ImportFile" accept="*.xlsx" class="col-xs-12 file-selector" />
</div>
<div class="col-xs-1">
<button class="btn btn-danger btn-xs" id="ImportFileBtn" type="submit" title="Import"><span class="glyphicon glyphicon-import"></span>Import</button>
</div>
</form>
</div>
</div>
<div class="row row-margin">
<div class="col-xs-12">
<div class="col-xs-3">
<div id="UploadStatusMessage"></div>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%">
0%
</div>
</div>
</div>
</div>
<div class="col-xs-12">
<div class="alert alert-default" id="PollingStatusMessage"></div>
</div>
</div>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<%:Scripts.Render("~/Scripts/jQueryForm") %>
</asp:Content>
ファイルアップロードコントローラCS
public class FileUploadController : ApiController
{
[HttpPost] //this is demo, lets assume that user is uploading a file and in the same method, some long running operation is happening.
public HttpResponseMessage Upload()
{
var requestId = HttpContext.Current.Request.Form["RequestTracker"];
if (HttpContext.Current.Request.Files.Count > 0)
{
var postedFile = HttpContext.Current.Request.Files[0];
var fileNameParts = postedFile.FileName.Split('\\');
var fileName = fileNameParts[fileNameParts.Length - 1];
fileName = string.Format("{0}_{1}", DateTime.Now.Ticks.ToString(), fileName);
string filePath = Path.Combine("c:\\temp", fileName);
postedFile.SaveAs(filePath);
}
//Note: usually, this will be some other operation (database insert/update, data validation etc)
//Inorder to show the exact status/progress, the backend should store some indication which can be retrieved using another ajax call by polling
ObjectCache cache = MemoryCache.Default;
cache.Remove(requestId);//remove any previous for demo purpose
CacheItemPolicy policy = new CacheItemPolicy();
policy.AbsoluteExpiration = DateTime.Now.AddMinutes(10);
List<int> taskStatus = new List<int>();
//long running task 1
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(100);
taskStatus.Add(i);
}
cache.Set(requestId, taskStatus, policy);
//long running task 2
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(100);
taskStatus.Add(i);
}
cache.Set(requestId, taskStatus, policy);
//long running task 3
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(100);
taskStatus.Add(i);
}
cache.Set(requestId, taskStatus, policy);
//long running task 4
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(100);
taskStatus.Add(i);
}
cache.Set(requestId, taskStatus, policy);
return Request.CreateResponse(HttpStatusCode.OK, "All Operations Completed");
}
}
ポーリングコントローラCS
public class PollingController : ApiController
{
[HttpPost]
public HttpResponseMessage GetStatus(UploadStatusRequest request)
{
ObjectCache cache = MemoryCache.Default;
var fileUploadStatus = cache.Get(request.RequestId) as List<int>;
var count = 0;
if (fileUploadStatus != null)
{
count = fileUploadStatus.Count;
}
return Request.CreateResponse(HttpStatusCode.OK, "Processed data : " + count + ". Please wait...");
}
}
typescriptファイル:
namespace jQueryForm {
export class FileUploadComponent {
progressBar: JQuery = $('.progress-bar');
importFile: JQuery = $('#ImportFile');
uploadStatusMessage: JQuery = $('#UploadStatusMessage');
pollingStatusMessage: JQuery = $('#PollingStatusMessage');
pollingInstance: any = null;
public RegisterEvents() {
var instance: FileUploadComponent = this;
instance.importFile.on('change', function() {
instance.ResetProgressBar();
});
var requestStatusTracker = null;
$('#ImportFileForm').ajaxForm({
beforeSubmit: function (arr, $form, options) {
requestStatusTracker = new Date().getMilliseconds();
arr.push({ name: 'RequestTracker', value: requestStatusTracker });
return true;
},
beforeSend: function (xhr, options) {
instance.ResetProgressBar();
instance.uploadStatusMessage.text('Uploading...');
},
//Note: The uploadProgress method displays the status of file transfer progress to web api method. Once the file is completely transferred to Web API method,
// the percentage will become 100. But, there could be other operations once the file is reached Web API and those are not counted.
uploadProgress: function (event, position, total, percentComplete) {
var percentVal = percentComplete + '%';
instance.progressBar.css("width", percentVal).attr("aria-valuenow", percentComplete).text(percentVal);
if (percentComplete == 100) {
var uploadStatusRequest = new Entities.UploadStatusRequest();
uploadStatusRequest.RequestId = requestStatusTracker;
instance.Poll(uploadStatusRequest);
instance.uploadStatusMessage.text('File Upload Complete.');
}
},
success: function (data) {
//instance.ResetProgressBar();
//Note: all operations completed in the web api method and the success response is received from the controller
clearTimeout(instance.pollingInstance);
instance.pollingStatusMessage.html(data);
},
error: function (xhr) {
},
complete: function (xhr) {//controller has completed all the action
}
});
}
private ResetProgressBar() {
this.progressBar.css("width", '0%').attr("aria-valuenow", 0).text('0%');
this.uploadStatusMessage.empty();
}
private Poll(uploadStatusRequest) {
var instance: FileUploadComponent = this;
instance.pollingInstance = setTimeout(function() {
$.ajax({
url: "api/Polling/GetStatus", data: uploadStatusRequest, dataType: "json", type: 'POST', success: function (data) {
//Update your status
instance.pollingStatusMessage.html(data);
//Setup the next poll recursively
instance.Poll(uploadStatusRequest);
}, error: function (xhr) {
instance.pollingStatusMessage.html(xhr.responseText);
}
});
}, 2000);
}
}
}
$(function() {
var fileUploadComponent = new jQueryForm.FileUploadComponent();
fileUploadComponent.RegisterEvents();
});
出力:以下に示すように進捗がユーザに表示される
、
新しいスレッドに処理をオフロードし、更新のためのJavaScriptポーリングを有する、またはSignalRを使用サーバーからクライアントに更新をプッシュします。 –
@JasonP、更新のためのjavascriptポーリング用のコードサンプル/リファレンスはありますか? –
私はちょうど 'setTimeout'か' setInterval'を使用します。もう1つのオプションが「永遠のフレーム」https://www.google.com/?q=forever%20frame%20iframe –