这个问题的背景是,用户通过浏览器上传文件或Excel数据到系统中,页面需要时时显示后台处理进度,以增强用户的体验。

在GitHub上找到一个一个项目,基本实现了这个功能,具体效果如下图

代码实现过程大概如下:

第一步 :定义一个HomeController类,用来处理浏览器的上传文件和进度情况

 public class HomeController : Controller
{
//
// GET: /Home/ public ActionResult Index()
{
return View();
} public ActionResult Homepage()
{
return View();
} [HttpPost]
public ActionResult GetUniqueIdentifier()
{
return Json(Guid.NewGuid().ToString());
} [HttpPost]
public ActionResult SingleFileUpload()
{
return View();
} [HttpPost]
public ActionResult MultipleFileUpload()
{
return View();
} [HttpPost]
public ActionResult DoUploadSingleFile(HttpPostedFileBase berkas, string guid)
{
bool result = false;
string filePath = Server.MapPath("~/Temporary/") + berkas.FileName; int fileLength = berkas.ContentLength;
HttpContext.Cache[guid + "_total"] = fileLength;
byte[] fileContent = new byte[fileLength];
int bufferLength = * ;
byte[] buffer = new byte[bufferLength];
int bytesRead = ; FileStream outputFileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite);
using (Stream inputFileStream = berkas.InputStream)
{
while ((bytesRead = inputFileStream.Read(buffer, , buffer.Length)) > )
{
outputFileStream.Write(buffer, , bytesRead);
outputFileStream.Flush(); HttpContext.Cache[guid + "_current"] = Convert.ToInt32(HttpContext.Cache[guid + "_current"]) + bytesRead;
Debug.WriteLine(HttpContext.Cache[guid + "_current"].ToString());
Thread.Sleep();
} inputFileStream.Close();
inputFileStream.Dispose();
} outputFileStream.Close();
outputFileStream.Dispose();
result = true; return Json(result);
} [HttpPost]
public ActionResult TrackProgress(string guid)
{
try
{
double paramCurrentFileSize = Convert.ToDouble(HttpContext.Cache[guid + "_current"]);
double paramTotalFileSize = Convert.ToDouble(HttpContext.Cache[guid + "_total"]);
int uploadProgress = Convert.ToInt32(paramCurrentFileSize * / paramTotalFileSize); return Json(uploadProgress);
}
catch (Exception)
{
return Json();
}
}
}

DoUploadSingleFile方法用来将用户传来的文件保存到Temporary目录下,将文件的总大小和已经写入的文件数量分别放到Cache中,以便接下来读取这两个数据。

TrackProgress方法就是讲DoUploadSingleFile方法总保存的两个数读出并计算比例。

第二步,Web页面,主要存放三部分,主要是上传组件和进度显示,通过JS绑定了按钮和上传送事件。

@using X_Cust_File_Upload.Helpers

@{
Layout = null;
ViewBag.Title = "SingleFileUpload";
} @*@PageHelper.Script("angular-js/js/angular.js", false)
@PageHelper.Script("underscore-js/js/underscore.js", false)*@
@PageHelper.Script("single-file-upload.js", true) <div class="title">
Single File Upload
</div> <div class="content">
<form method="post" enctype="multipart/form-data" id="form_upload" name="form_upload" style="display: none;">
<input type="file" name="berkas" id="berkas" />
</form> <div class="control-group">
<div class="input-prepend">
<button class="btn" id="buttonSelectFile"><i class="icon icon-folder-open"></i></button>
<input type="text" name="berkas_name" id="berkas_name" class="span3 uneditable-input" placeholder="Select File to Upload" />
</div> <button class="btn btn-primary" id="buttonUploadFile"><i class="icon icon-upload"></i> Upload File</button> <div id="notification-area" class="alert info pull-right notification-area">
</div>
</div>
</div> <script type="text/javascript">
$(document).ready(function () {
$("#buttonSelectFile").on("click", function (event) {
$("#berkas").trigger("click");
}); $("#berkas").on("change", function (event) {
$("#berkas_name").val($("#berkas").val());
}); $("#buttonUploadFile").on("click", function (event) {
var notificationArea = new NotificationArea($("#notification-area")); var fileUpload = new FileUpload();
fileUpload.uploadSingleFile($("#form_upload"), "87shd-09ld2-9sdkl-09dlp-02kdm", "@Url.Content("~/Home/DoUploadSingleFile")", notificationArea, "@Url.Content("~/Home/TrackProgress")");
});
});
</script>

第三步,主要是ajax上传事件,即single-file-upload.js文件,在上传数据的时候,开启一个定时器,每个1s向TrackProgress方法发送一次请求,获取已经上传的进度。

function NotificationArea($container) {
this.showProgressNotification = function ($progress, $isVisible) {
$container.html("<span>Progress : " + $progress + " %</span>"); if ($isVisible == false) {
$container.fadeIn();
}
}; this.showErrorNotification = function () {
$container.removeAttr("class");
$container.addClass("alert error pull-right");
$container.html("<span>Upload error.</span>");
}; this.showSuccessNotification = function () {
$container.removeAttr("class");
$container.addClass("alert info pull-right");
$container.html("<span>Uploaded successfully.</span>");
};
} function FileUpload() {
this.guid = "";
this.onUploadProgress = false;
this.notificationObject = null;
this.trackUrl = ""; this.uploadSingleFile = function ($form, $guid, $url, $notificationObject, $trackUrl) {
if ($form != null) {
this.guid = $guid;
//this.notificationObject = $notificationObject;
this.trackUrl = $trackUrl;
var trackTimer = setInterval(function () {
trackUploadProgress($trackUrl, $notificationObject, $guid);
}, 1000); $form.ajaxSubmit({
url: $url,
data: {
guid: $guid
},
beforeSend: function () {
$notificationObject.showProgressNotification(0, false);
},
success: function (data) {
console.log("sukses"); if (data == true) {
clearTimeout(trackTimer);
$notificationObject.showSuccessNotification();
}
else {
$notificationObject.showErrorNotification();
}
},
error: function (xhr, ajaxOptions, error) {
$notificationObject.showErrorNotification();
},
complete: function () {
clearTimeout(trackTimer);
}
});
}
};
} function trackUploadProgress($url, $notificationObject, $guid) {
console.log("Upload progress"); $.ajax({
url: $url,
type: "post",
data: {
guid: $guid
},
success: function (data) {
$notificationObject.showProgressNotification(data, true);
}
});
}

到此,主要功能已经完成,上传文件可以看到大致的进度。

但是我将这个功能集成到自己的系统时候遇见了一个很奇怪的问题:进度一直不提示,直到数据上传成功了,提示显示100%。这个问题的原因还不确定,请院子里的大牛帮忙分析下。

在原有的系统上增加权限验证功能,如果用户没有登录系统是不能上传数据的,但也就是这个功能,造成了上面的问题。我的做法如下:

第四步,增加AuthorizeAttribute认证子类,主要功能是用来判断用户是否登录系统,如果没有登录,跳转到登录页面,让用户登录。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
} protected override bool AuthorizeCore(HttpContextBase httpContext)
{ if (httpContext == null)
{
throw new ArgumentNullException("httpContext");
}
if (!httpContext.User.Identity.IsAuthenticated)//未登录的话 跳转到登录界面
return false;
return true;
} protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectResult("/Auth/LogOn");
}
}

第五步,用户登录成功后,跳转到上传页面,这个工程使用ajax登录,JS代码如下:

$.ajax({
type: "POST",
url: "LogOn",
data: { name: $("#UserName").val(), pwd: $("#Password").val(), vlidateCode: $.trim($("#ValidateCode").val())},
dataType: "json",
success: function (data) {
if(data.isSuccess)
{
window.location = data.url;
}
else
{
alert(data.message);
changeCheckCode();
}
$("#Loading").hide();
}
});

后台登录过程为AuthorController类,主要设置用户已经登录标志,

 [HttpPost]
public JsonResult LogOn(string name, string pwd, string vlidateCode)
{
FormsAuthentication.SetAuthCookie(name, false);
var json = new { isSuccess = true, url = "../Home" };
return Json(json);
}

第六步,在HomeController类上添加认证属性

  [CustomAuthorize(Roles="T1")]
public class HomeController : Controller
{
........
}

原作者程序地址:http://files.cnblogs.com/files/crazyguo/x-cust-file-upload-master.zip

我增加后的程序:http://files.cnblogs.com/files/crazyguo/My.7z

  

Asp.Net MVC页面显示后台处理进度问题的更多相关文章

  1. ASP.NET MVC搭建项目后台UI框架—5、Demo演示Controller和View的交互

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  2. ASP.NET MVC搭建项目后台UI框架—7、统计报表

    ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NET M ...

  3. ASP.NET MVC搭建项目后台UI框架—8、将View中选择的数据行中的部分数据传入到Controller中

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  4. ASP.NET MVC搭建项目后台UI框架—1、后台主框架

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  5. ASP.NET MVC搭建项目后台UI框架—2、菜单特效

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  6. ASP.NET MVC搭建项目后台UI框架—3、面板折叠和展开

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  7. ASP.NET MVC搭建项目后台UI框架—4、tab多页签支持

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  8. ASP.NET MVC搭建项目后台UI框架—6、客户管理(添加、修改、查询、分页)

    目录 ASP.NET MVC搭建项目后台UI框架—1.后台主框架 ASP.NET MVC搭建项目后台UI框架—2.菜单特效 ASP.NET MVC搭建项目后台UI框架—3.面板折叠和展开 ASP.NE ...

  9. jsp实时显示后台批处理进度 - out分块,简单的长连接方式

    这两天在实现一个批处理操作,但是想让前台实时显示后台批处理进度,本想着用复杂一些的框架可以实现异步信息调用 但是鉴于是内部管理系统,且只有一两个人用到这个功能,所以做了一个简单的长连接方式的实时响应 ...

随机推荐

  1. JMeter Sampler之BeanShellSampler的使用

    Sampler之BeanShellSampler的使用 by:授客 QQ:1033553122 欢迎加入软件性能测试交流群:7156436 1.  Bean Shell简介 ·         Bea ...

  2. loadrunner 运行脚本-Run-time Settings-ContentCheck简单设置

    运行脚本-Run-time Settings-ContentCheck简单设置 by:授客 QQ:1033553122 ContentCheck的设置可用来让VuGen检测存在错误的站点页面.如果被测 ...

  3. loadrunner 脚本开发-基本知识

    脚本开发-基本知识 1)编码工具设置 自动补全输入Tools->General Options->Environment->Auto complete word 显示功能语法Tool ...

  4. 修复cocos2dx的Label,WP8下不能换行的问题

    注:2014年12月23日有内存/性能优化更新,内容在下面分割线后 搞了几个小时,这个头疼的问题,我给出代码吧. 找到 libcocos2d/platform/winrt/CCFreeTypeFont ...

  5. 使用windows命令和iconv.exe批量转换文件编码

    iconv是知名的开源跨平台编码转换库,iconv.exe是iconv库在windows下的命令行工具,iconv.exe的一般用法:iconv.exe -f gbk -t utf-8 gbk.txt ...

  6. 【redis专题(5)】命令语法介绍之sets

    标签(空格分隔): Redis 关于 redis的无序集合有三个特点: 无序性, 确定性(描述准确) , 唯一性: 有点类似于数据容器: 增 SADD key member1 [member2] 作用 ...

  7. MySQL8.0——Resource Group(资源组)

    资源组介绍 简介 MySQL是单进程多线程的程序,MySQL线程包括后台线程(Master Thread.IO Thread.Purge Thread等),以及用户线程.在8.0之前,所有线程的优先级 ...

  8. Gradle的介绍与安装

    Gradle简介 Gradle是一款致力于自动化构建和对多种开发语言的支持的构建工具.如果你想在任意开发平台上构建.测试.发布和部署软件,那么Gradle提供了一个非常灵活的模型,可以支持整个开发生命 ...

  9. C#泛型约束where T : class 解释

    这是参数类型约束,指定T必须是Class类型. .NET支持的类型参数约束有以下五种:where T : struct                               | T必须是一个结构 ...

  10. 合并多个Excel文件

    这条分享来自百度经验https://jingyan.baidu.com/article/e6c8503cb6ed7ee54e1a1811.html