这个问题的背景是,用户通过浏览器上传文件或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. Linux 时间及时区设置

    时间以及时区设置 by:授客 QQ:1033553122 1.首先确认使用utc还是local time. UTC(Universal Time Coordinated)=GMT(Greenwich ...

  2. flow-vue.js移动端效果

    得益于vue.js和element,以及vue-element-extends在线表格编辑.前后端分离的后端用golang+beego框架,服务器采用腾讯云. vue的自适应做的很好,只要将侧栏加一行 ...

  3. 洗礼灵魂,修炼python(51)--爬虫篇—变色龙般的伪装

    变色龙原理 变色龙这种动物想必大家都了解,它们会根据周遭环境的局势来改变自己的颜色,伪装自己. 那么爬虫有这种技能吗?当然是有的,先不着急说这个问题. 从上一篇开始,你有没有想过,站在网站管理的角度, ...

  4. 【PAT】B1059 C语言竞赛(20 分)

    这个题也是个逻辑问题 此题用我这种方式很复杂,应该用map 用两个分别储存成绩,已领过奖的人, #include<stdio.h> #include<math.h> int a ...

  5. 回文数的golang实现

    判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数 输入: 输出: true 输入: - 输出: false 解释: 从左向右读, 为 - . 从右向左读, 为 - ...

  6. Nginx服务器的图片防盗链

    全站的防盗链方法 在/usr/local/webserver/nginx/conf//vhost/xxxx.conf文件要添加防盗链的server段里添加下面的代码: location ~ .*\.( ...

  7. hadoop系列 第二坑: hive hbase关联表问题

    关键词: hive创建表卡住了 创建hive和hbase关联表卡住了 其实针对这一问题在info级别的日志下是看出哪里有问题的(为什么只能在debug下才能看见呢,不太理解开发者的想法). 以调试模式 ...

  8. CSS 中伪类的顺序

    因为css渲染方式的关系: 快速记忆方法:LoVe HAte 原则: L:link V:vistered H:hover A:active li :link { color: greenyellow; ...

  9. (16)Python练习题

    练习题一: 练习题二:

  10. Android Studio IDE的 LogCat如何过滤指定应用的调试信息

    http://blog.csdn.net/wangqing830414/article/details/40377979 打开 LogCat在搜索框右侧的No Filters中选择 Edit Filt ...