我可能会使用 jQuery 的 ajaxForm() 提交表单。
然后,onSuccess 调用一个函数,该函数开始进一步的 AJAX 请求,以使用 JSON 轮询来自您的网络服务器的上传进度。除了有一个 URL 来处理 ASP.NET 中的文件上传之外,您还需要有另一种方法来以 JSON 格式返回某种异步工作者的进度。
一旦你得到 JSON,你就可以把它提供给一个 jQueryUI 进度条。
例如,在一个 ASP .NET MVC 应用程序中,我做了这样的事情:
在 Upload.aspx 视图中,开始提交
<% using (Html.BeginForm(null, null, FormMethod.Post, new { enctype = "multipart/form-data", id = "UploadForm" }))
{ %>
<div>
<input type="file" name="CSVFile" id="CSVFile" />
<button>Upload</button>
</div>
<% } %>
var pb = $('#prog');
var pbContainer = $('#pbcont');
var pbPercent = $('#progp');
var uploadForm = $('#UploadForm');
var status = $('#StatusDetail');
uploadForm.ajaxForm({
iframe: true,
dataType: 'jason',
success: function (data) {
beginProcessing($.parseJSON($(data).text()), '" + Url.Action("UploadStatus", "Upload") + @"', pb, pbContainer, status, pbPercent);
},
error: function (xhr, textStatus, error) {
alert('Error: ' + textStatus);
}
});
处理初始上传的控制器方法
在这里,我正在为上传开始时创建一个唯一 ID,这样我可以稍后在我想知道它的进度时识别上传。
我正在使用我编写的一个工作类,它异步处理处理 - 这是您希望异步开始将数据插入数据库的地方。
当我们到达这个控制器方法时,FileStream 应该已经到达服务器,因此我们可以将它传递给我们的工作人员以读取流、解析 CSV 并完成数据库工作。请注意,在这里,我将 StreamReader 传递给我的工作人员,以便它可以处理所有这些。
// NOTE: The parameter to this action MUST match the ID and Name parameters of the file input in the view;
// if not, it won't bind.
[HttpPost]
public JsonResult Upload(HttpPostedFileBase CSVFile)
{
try
{
if (CSVFile == null || String.IsNullOrWhiteSpace(CSVFile.FileName))
return Json("You must provide the path to your CSV file", "text/plain");
if (!CSVFile.FileName.ToLower().Contains(".csv"))
return Json("You can only upload CSV files", "text/plain");
Guid id = worker.BeginImport(dataReporistory, new StreamReader(CSVFile.InputStream));
//return some JSON
var json = new
{
ID = id,
name = CSVFile.FileName,
size = CSVFile.ContentLength
};
return Json(json, "text/plain");
}
catch (Exception e)
{
return Json(Utilities.DisplayExceptionMessage(e), "text/plain");
}
}
返回进度更新的控制器方法
[HttpPost]
public JsonResult UploadStatus(Guid id)
{
UploadJob job = Worker.GetJobStatus(id);
return Json(job);
}
视图中的 JavaScript 处理进度条更新
正如您将在上面看到的,当文件完成上传时,ajaxForm.Submit() 方法将在 onSuccess 事件期间从此处调用 beginProcessing()。
它还将传递从 Upload() 控制器方法中获取的 JSON,该方法告诉我们的视图在从我们的工作人员获取作业进度时要传递给更新 URL 的上传 ID。
一旦 beginProcessing 被调用,它会做一些工作来设置一个进度条,但基本上然后开始在设置的计时器间隔上调用 updateProgress()。 updateProgress 是完成从网络服务器的 UploadStatus 页面获取 JSON 的所有工作的函数。
一旦 updateProgress 从网络服务器获取 JSON 更新,它会做一些工作将其馈送到插入到页面上的 div 中的 jQuery UI 进度条中。
<div id="pbcont">
<p style="display: inline-block;"><strong>Processing...</strong></p>
<h3 style="display: inline-block;" id="progp"></h3>
<div id="prog"></div>
<br />
<div id="StatusDetail"></div>
</div>
function beginProcessing(response, url, pb, pbContainer, statusContainer, pbPercent) {
if (!response.ID) {
alert('Error: ' + response);
return;
}
pb.progressbar({
value: 0
});
pbContainer
.css('opacity', 0)
.css('display', 'block');
//Set the interval to update process.
var hasUpdated = false;
var intervalID = setInterval(function () {
updateProgress(url + '/' + response.ID, pb, statusContainer, pbPercent, intervalID);
}, 500);
}
function updateProgress(url, pb, statusContainer, pbPercent, intervalID) {
//Make an AJAX post to get the current progress from the server
$.post(url,
function (job) {
var newValue = 0;
var currentValue = pb.progressbar('value');
//The percentage value retrived from server:
newValue = (job != null && job.TotalItems != 0 ? (job.ProcessedItems / job.TotalItems * 100) : 0);
if (newValue > 0)
hasUpdated = true;
if (hasUpdated && job == null) {
newValue = 100;
statusContainer.html("<strong>Status:</strong> Finished");
clearInterval(intervalID);
}
if (!hasUpdated)
currentValue = currentValue + 1;
newValue = Math.max(currentValue, newValue);
pb.progressbar("value", newValue);
pbPercent.text(Math.round(newValue, 0) + '%');
if (job != null)
statusContainer.html("<strong>Upload:</strong> " + job.Status);
});
}