这个问题的背景是,用户通过浏览器上传文件或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. 程序员Web面试之JSON

    JSON是什么? JSON(JavaScript对象表示法), 是在网络通信下,常用的一种数据表达格式,它有助于我们于一个自描述的,独立的和轻的方式呈现并交换数据.这些数据可以易于和转换为JavaSc ...

  2. 网络基础 cookie详解

    cookie详解 by:授客 QQ:1033553122 cookie干嘛用的? 参见文章http 会话(session)详解: 网络基础 http 会话(session)详解   cookie分类 ...

  3. JavaScript按IP地址排序

    JavaScript按IP地址列表排序,主要思路就是分割每个点号部分,然后ip1和ip2分别对不够三位数的进行补0操作,然后转换为数字类型进行一一比较. 上代码: 正序: var arr=[ {ip: ...

  4. 程序员简单打造一个灵活智能的自动化运维系统C#实例程序

    你是一个程序员,被派去管理公司500台计算机.这些机器可能需要执行一些自动化任务,一台台手动操作会把你累死.重复性的工作还是交给电脑处理,怎么解决这个问题呢?一个自动化的运维系统是必须的.自己实现的好 ...

  5. Python CNN卷积神经网络代码实现

    # -*- coding: utf-8 -*- """ Created on Wed Nov 21 17:32:28 2018 @author: zhen "& ...

  6. WebAPi使用Autofac实现依赖注入

    WebAPi依赖注入  使用记录 笔记 1.NuGet包安装 2.控制器加入构造函数 3.Global.asax  ----Application_Start 应用程序启动时 using Autofa ...

  7. Django框架的使用教程--站点的管理[七]

    Django的站点管理 创建超级管理员命令(密码要8位) python manage.py createsuperuser 进入站点管理 注册模型类 from django.contrib impor ...

  8. MySQL sql_mode=only_full_group_by错误

    今天在测试服务器上突然出现了这么一个MySQL的问题,同样的代码正式服没有问题,那肯定就是出在了配置上,查了一下原因才明白原来是数据库版本为5.7以上的版本, 默认是开启了 only_full_gro ...

  9. asp.net core 如何集成kindeditor并实现图片上传功能

     准备工作 1.visual studio 2015 update3开发环境 2.net core 1.0.1 及以上版本  目录 新建asp.net core web项目 下载kindeditor ...

  10. golang的reflection(转)

    作者:BGbiao 链接:https://www.jianshu.com/p/42c19f88df6c 來源:简书 反射reflection 可以大大提高程序的灵活性,使得interface{}有更大 ...