asp.net单文件带进度条上传的解决方案

   2015-09-11 0
核心提示:本文介绍的asp.net单文件带进度条上传,不属于任务控件,也不是flash类型的上传,完全是asp.net、js、css实现上传,需要的朋友可以参考下

最近做项目中遇到很多问题,比如带进度条的文件上传,看了网上很多资料还没找到真正意义上的ASP.NET实现进度条上传(可能是我没找到),下面我来跟大家分享一下我实现的这个程序。
首先看下界面效果,当然你可以完全修改界面为你自己所用。

asp.net单文件带进度条上传的解决方案

先解释一下这个程序,该程序采用了jquery框架,实现了小文件上传,不超过80Mb,可以在web.config文件中进行相应的配置,但是有个最大值,具体需要查看msdn。开发环境采用visual studio 2013 .net framework 4.5,运行的时候大家注意一下是否满足要求,好了,下面直入正题。
先来看看实现原理。基本原理:一个页面进行文件上传,另外一个页面去监听这个文件上传了多少。
这里面有两个地方需要解释一下:第一个,如何知道监听的这个文件就是上传的这个文件?实现机制很简单,就是让asp.net产生一个唯一的guid,这个id序号是唯一的,通过ajax取出来赋值给一个隐藏字段;第二个,如何获取guid标志的文件信息?通过asp.net缓存机制实现,上传的过程中,不断的将上传信息往缓存里面写,直到文件上传完成,而在另外一个通过guid获取缓存的信息,信息包括你想要的信息,比如上传了多少字节、消耗了多长时间等。好了,要点就解释到这里,有疑问的话给我留言。
下面来说说具体的实现:
文件目录结构如下:

 asp.net单文件带进度条上传的解决方案

index.htm就是文件上传页面,提交form给UploadHandler目录下的Default.aspx,以实现文件上传。
ProgressHandler目录下三个文件为Abort.ashx、GenericGuid.ashx,Handler.ashx功能分别为:根据Guid取消正在上传的文件,生成Guid,根据Guid获取上传信息。
第一步:建立index.htm页面,这个上传页面,需要注意的就是需要一个隐藏的iframe,并且名字为form提交的目标。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
 <title>ASP.NET Ajax文件上传进度条示例</title> 
 <meta name="author" content="李检全" /> 
 <link href="Styles/base.css" rel="stylesheet" type="text/css" /> 
 <script src="Scripts/jquery-1.4.2.min.js" type="text/javascript"></script> 
 <script src="Scripts/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script> 
 <script src="Scripts/ljq.lib.js" type="text/javascript"></script> 
 <script src="Scripts/Ajax/GuidGet.js" type="text/javascript"></script> 
 <script src="Scripts/Ajax/ajax-progress-upload.js" type="text/javascript"></script> 
</head> 
<body> 
 <div id="upload_demo"> 
  <div class="title">ASP.NET Ajax 文件上传进度条示例</div> 
  <form action="UploadHandler/Default.aspx" enctype="multipart/form-data" method="post" target="upload_hidden_iframe"> 
   <input id="guid" name="guid" value="" type="hidden" /> 
   <p>*本程序适合小文件上传,不超过80Mb</p> 
   <p>文件地址</p> 
   <input name="upload_file" type="file" /> 
   <br /> 
   <p>文件描述</p> 
   <textarea name="description_file"></textarea> 
   <br /> 
   <br /> 
   <input type="submit" value="上传文件" /> 
  </form> 
 </div> 
 <div id="back_panel"></div> 
 <div id="upload_panel"> 
  <div id="upload_title">文件上传</div> 
  <div id="upload_content"> 
 
   <ul> 
    <li id="finished_percent">正在准备上传...</li> 
    <li><div id="upload_bar"><div id="upload_progress"></div></div></li> 
    <li id="upload_speed"></li> 
    <li id="upload_costTime"></li> 
    <li id="upload_fileSize"></li> 
    <li id="upload_fileName"></li> 
   </ul> 
 
   <div id="upload_detail"></div> 
   <div id="upload_choose"> 
    <span id="upload_cancel">取消</span><span id="upload_submit">确定</span> 
   </div> 
  </div> 
 </div> 
 <iframe name="upload_hidden_iframe" style="display:none;"></iframe> 
 
 
</body> 
</html> 

第二步,创建GenerateGuid.ashx文件,作用就是生成唯一的Guid。

<%@ WebHandler Language="C#" Class="ProgressHandler.Handler" %> 
 
using System; 
using System.Web; 
using System.Xml.Linq; 
 
namespace ProgressHandler 
{ 
 public class Handler : IHttpHandler 
 { 
  /// <summary> 
  /// 获得上传文件的GUID 
  /// </summary> 
  /// <param name="context">当前请求实体</param> 
  /// <creattime>2015-06-28</creattime> 
  /// <author>FreshMan</author> 
  public void ProcessRequest(HttpContext context) 
  { 
   context.Response.Charset = "utf-8"; 
   context.Response.ContentType = "application/xml"; 
   var guid = Guid.NewGuid().ToString(); 
   var doc = new XDocument(); 
   var root = new XElement("root"); 
 
   var xGuid = new XElement("guid", guid); 
   root.Add(xGuid); 
   doc.Add(root); 
   context.Response.Write(doc.ToString()); 
   context.Response.End(); 
  } 
 
  public bool IsReusable 
  { 
   get { return false; } 
  } 
 
 } 
} 

第三步,创建Default.aspx文件,用于提交表单时上传文件。

using System; 
 
namespace UploadHandler 
{ 
 public partial class UploadHandlerDefault : System.Web.UI.Page 
 { 
  protected void Page_Load(object sender, EventArgs e) 
  { 
   string guid = Request.Params["guid"]; 
   UploadUtil utilHelp = new UploadUtil(this, guid); 
   utilHelp.Upload(); 
  } 
 } 
} 

上传核心代码:

using System; 
using System.Web; 
using System.IO; 
using System.Configuration; 
using System.Web.UI; 
using System.Web.Caching; 
using System.Threading; 
public class UploadUtil 
{ 
 private Stream _reader; 
 private FileStream _fStream; 
 private const int Buffersize = 10000; 
 private readonly string _filePath =new Page().Server.MapPath(ConfigurationManager.AppSettings["upload_folder"]); 
 private readonly Page _page; 
 private readonly string _guid; 
 public UploadUtil(Page page, string guid) 
 { 
  _page = page; 
  _guid = guid; 
 } 
 public void Upload() 
 { 
  if (_page.Request.Files.Count > 0) 
  { 
   DoUpload(_page.Request.Files[0]); 
  } 
 } 
 private void DoUpload(HttpPostedFile postedFile) 
 { 
  bool abort = false; 
  string uploadFilePath = _filePath + DateTime.Now.ToFileTime()+"//"; 
  if (!Directory.Exists(uploadFilePath)) 
  { 
   Directory.CreateDirectory(uploadFilePath); 
  } 
  string uploadFileName = postedFile.FileName; 
  DownloadingFileInfo info = new DownloadingFileInfo(uploadFileName, postedFile.ContentLength, postedFile.ContentType); 
  object fileObj = HttpContext.Current.Cache[_guid]; 
  if (fileObj != null) 
  { 
   HttpContext.Current.Cache.Remove(_guid); 
  } 
  HttpContext.Current.Cache.Add(_guid, info, null, DateTime.Now.AddDays(1), TimeSpan.Zero, CacheItemPriority.AboveNormal, null); 
  DateTime begin=DateTime.Now.ToLocalTime(); 
  _fStream = new FileStream(uploadFilePath + uploadFileName, FileMode.Create); 
  _reader = postedFile.InputStream; 
  byte []buffer=new byte[Buffersize]; 
  int len = _reader.Read(buffer,0,Buffersize); 
 
  while (len > 0&&!abort) 
  { 
   _fStream.Write(buffer,0,len); 
   DateTime end = DateTime.Now.ToLocalTime(); 
   info.CostTime = (long)(end - begin).TotalMilliseconds; 
   info.FileFinished += len; 
 
   //模拟延时用,实际应用的时候注销他 
   Thread.Sleep(1000); 
 
   HttpContext.Current.Cache[_guid] = info; 
   abort=((DownloadingFileInfo)HttpContext.Current.Cache[_guid]).Abort; 
   len = _reader.Read(buffer,0,Buffersize); 
  } 
  
  _reader.Close(); 
  _fStream.Close(); 
  if (abort) 
  { 
   if (File.Exists(uploadFilePath + uploadFileName)) 
   { 
    File.Delete(uploadFilePath + uploadFileName); 
   } 
  } 
 } 
  
}

 

第四步,创建Handler.ashx文件,用于查看文件上传情况。

<%@ WebHandler Language="C#" Class="ProgressHandler.Handler" %> 
 
using System.Web; 
using System.Xml.Linq; 
 
namespace ProgressHandler 
{ 
 public class Handler : IHttpHandler 
 { 
  /// <summary> 
  /// 获得上传文件的进度 
  /// </summary> 
  /// <param name="context">当前请求实体</param> 
  /// <creattime>2015-06-28</creattime> 
  /// <author>FreshMan</author> 
  public void ProcessRequest(HttpContext context) 
  { 
   context.Response.ContentType = "application/xml"; 
   context.Response.Charset = "utf-8"; 
   var guid = context.Request.Form["guid"]; 
   var info = context.Cache[guid] as DownloadingFileInfo; 
   var doc = new XDocument(); 
   var root = new XElement("root"); 
   if (info != null) 
   { 
    var fileName = new XElement("fileName", info.FileName); 
    var fileFinished = new XElement("fileFinished", info.FileFinished); 
    var fileSize = new XElement("fileSize", info.FileSize); 
    var costTime = new XElement("costTime", info.CostTime); 
    var fileState = new XElement("fileState", info.FileState); 
    var speed = new XElement("speed", info.Speed); 
    var percent = new XElement("percent", info.Percent); 
    var abort = new XElement("abort", false); 
    root.Add(fileName); 
    root.Add(fileFinished); 
    root.Add(fileSize); 
    root.Add(costTime); 
    root.Add(fileState); 
    root.Add(speed); 
    root.Add(percent); 
    if (info.Abort) 
    { 
     abort.Value = info.Abort.ToString(); 
     context.Cache.Remove(guid); 
    } 
    if (info.FileState == "finished") 
    { 
     context.Cache.Remove(guid); 
    } 
   } 
   else 
   { 
    var none = new XElement("none", "no file"); 
    root.Add(none); 
   } 
   doc.Add(root); 
   context.Response.Write(doc.ToString()); 
   context.Response.End(); 
  } 
 
  public bool IsReusable 
  { 
   get { return false; } 
  } 
 } 
} 

第五步,创建Abort.ashx文件,用于取消上传。

 <%@ WebHandler Language="C#" Class="ProgressHandler.Abort" %> 
using System.Web; 
using System.Xml.Linq; 
 
namespace ProgressHandler 
{ 
 public class Abort : IHttpHandler 
 { 
  /// <summary> 
  /// 取消上传处理程序 
  /// </summary> 
  /// <param name="context">当前请求实体</param> 
  /// <creattime>2015-06-28</creattime> 
  /// <author>FreshMan</author> 
  public void ProcessRequest(HttpContext context) 
  { 
   context.Response.ContentType = "application/xml"; 
   context.Response.Charset = "utf-8"; 
   var guid = context.Request.Form["guid"]; 
   var abort = !string.IsNullOrEmpty(context.Request.Form["abort"]); 
   var info = context.Cache[guid] as DownloadingFileInfo; 
   if (info != null) 
   { 
    info.Abort = abort; 
    context.Cache[guid] = info; 
   } 
   var doc = new XDocument(); 
   var root = new XElement("root"); 
   var flag = new XElement("flag", info == null  "false" : "true"); 
   root.Add(flag); 
   doc.Add(root); 
   context.Response.Write(doc.ToString()); 
   context.Response.End(); 
  } 
 
  public bool IsReusable 
  { 
   get { return false; } 
  } 
 
 } 
} 

好了,下面就是编写javascript脚本了,我引用了jquery这个框架,另外还用了ui框架。
核心代码是ajax-progress-upload.js文件,另外还有一个获取guid的文件。

$(document).ready(function () { 
 var _guid_url = "ProgressHandler/GenerateGuid.ashx"; 
 var _progress_url = "ProgressHandler/Handler.ashx"; 
 var _abort_url = "ProgressHandler/Abort.ashx"; 
 var _target = "#guid"; 
 var _guid = ""; 
 var _cancel = false; 
 var _timer; 
 LJQ.setGuid(_target, _guid_url); 
 $("#upload_panel").draggable({ handle: "#upload_title" }); 
 $("#upload_choose span").hover(function () { 
  $(this).css({ 
   "color": "#f6af3a", 
   "border": "1px solid #e78f08" 
  }); 
 }, function () { 
  $(this).css({ 
   "color": "#1c94cd", 
   "border": "1px solid #ddd" 
  }); 
 }); 
 $("#upload_cancel").click(function () { 
  $.ajax({ 
   url: _abort_url, 
   data: { guid: _guid, abort: true }, 
   dataType: "xml", 
   type: "post", 
   success: function () { 
 
    $("#upload_panel").fadeOut('fast'); 
    $("#back_panel").fadeOut(1000); 
    window.clearInterval(_timer); 
   } 
  }); 
 
 
 }); 
 $("#upload_submit").click(function () { 
  $("#upload_panel").fadeOut('fast'); 
  $("#back_panel").fadeOut("1000"); 
 }); 
 $("form").submit(function () { 
  _guid = $(_target).val(); 
  if ($("input[name='upload_file']").val() == "") { 
   alert("未指定上传文件!"); 
   return false; 
  } 
  $("#upload_progress").css("width", "0%"); 
  $("#finished_percent").html("准备上传..."); 
  $("#upload_speed").html(""); 
  $("#upload_fileName").html(""); 
  $("#upload_fileSize").html(""); 
  $("#upload_costTime").html(""); 
  var _option = { 
   url: _progress_url, 
   data: { guid: _guid }, 
   dataType: "xml", 
   type: "post", 
   beforeSend: function () { 
    $("#back_panel").fadeTo('fast', '0.5'); 
    $("#upload_panel").fadeIn('1000'); 
   }, 
   success: function (response) { 
 
    if ($(response).find("root abort").text() == "true") { 
     $("#upload_panel").fadeOut('fast'); 
     $("#back_panel").fadeOut(1000); 
     window.clearInterval(_timer); 
    } 
 
    else if ($(response).find("root none").text() == "no file") { 
 
    } 
    else { 
     var _percent = ($(response).find("root percent").text() * 100); 
     var _speed = $(response).find("root speed").text(); 
     var _fileSize = $(response).find("root fileSize").text(); 
     var _upload_costTime = $(response).find("root costTime").text(); 
     if (parseInt(_speed) < 1024) { 
      _speed = LJQ.toFix(_speed) + "Kb"; 
     } else { 
      _speed = LJQ.toFix(_speed / 1024) + "Mb"; 
     } 
 
     if (parseInt(_fileSize) / 1024 < 1024) { 
      _fileSize = LJQ.toFix(_fileSize / 1024) + "Kb"; 
     } else if (parseInt(_fileSize) / 1024 / 1024 < 1024) { 
      _fileSize = LJQ.toFix(_fileSize / 1024 / 1024) + "Mb"; 
     } else { 
      _fileSize = LJQ.toFix(_fileSize / 1024 / 1024 / 1024) + "Gb"; 
     } 
 
     if (_upload_costTime < 1000) { 
      _upload_costTime = _upload_costTime + "毫秒"; 
     } else if (_upload_costTime / 1000 < 60) { 
      _upload_costTime = parseInt(_upload_costTime / 1000) + "秒" + _upload_costTime % 1000 + "毫秒"; 
     } else { 
      _upload_costTime = parseInt(_upload_costTime / 1000 / 60) + "分" + parseInt((_upload_costTime % 60000) / 1000) + "秒" + _upload_costTime % 1000 + "毫秒"; 
     } 
     $("#upload_progress").css("width", parseInt(_percent) + "%"); 
     $("#finished_percent").html("完成百分比:" + LJQ.toFix(_percent) + "%"); 
     $("#upload_speed").html("上传速度:" + _speed + "/sec"); 
     $("#upload_fileName").html("文件名称:" + $(response).find("root fileName").text()); 
     $("#upload_fileSize").html("文件大小:" + _fileSize); 
     $("#upload_costTime").html("上传耗时:" + _upload_costTime); 
     if (_percent >= 100) { 
 
      window.clearInterval(_timer); 
      $("#finished_percent").html("<span style='color:green;'>文件上传完成</span>"); 
     } 
     if (_cancel) { 
      window.clearInterval(_timer); 
     } 
    } 
 
   }, 
   error: function () { } 
  }; 
 
  _timer = window.setInterval(function () { $.ajax(_option); }, 1000); 
 
 }); 
 
}); 

以上为代码的主要部分。asp.net单文件带进度条上传,不属于任务控件,也不是flash类型的上传,完全是asp.net、js、css实现上传。源码为开发测试版,需要使用的亲需要注意修改配置文件。

项目源码下载请点击这里:http://xiazai.jb51.net/201509/yuanma/asp_net_progressbar(jb51.net).rar

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • [VB][ASP.NET]FileUpload控件「批次上传 / 多档
    FileUpload控件「批次上传 / 多档案同时上传」的范例 (VB语法) http://www.dotblogs.com.tw/mis2000lab/archive/2008/05/14/3986.aspx    FileUpload控件真的简单好用,不使用它来作批次上传,却要改用别的方法,实在不聪明。要用就一次用到底,公开File
    02-10
  • 使用WebClient自动填写并提交ASP.NET页面表单的源代码
    使用WebClient自动填写并提交ASP.NET页面表单的
    转自:http://www.cnblogs.com/anjou/archive/2007/03/07/667253.html 在.NET中通过程序填写和提交表单还是比较简单。比如,要提交一个如下图所示的登录表单:           填写和提交以上表单的代码如下:       // 要提交表单的URI字符串
    02-09
  • asp.net mvc多条件+分页查询解决方案
    


            
asp.net mvc多条件+分页查询解决方案
    asp.net mvc多条件+分页查询解决方案
    http://www.cnblogs.com/nickppa/p/3232535.html开发环境vs2010css:bootstrapjs:jquery    bootstrap paginator原先只是想做个mvc的分页,但是一般的数据展现都需要检索条件,而且是多个条件,所以就变成了MVC多条件+分页查询因为美工不是很好,所以用的是
    02-09
  • ASP.NET操作Cookies的问题(Bug or Not)
    以下存和取都是在不同的页面中,如果是在同一个页面也没必要用cookies了。 Test1: 给Cookies赋值: const string AAA="aaa"; Response.Cookies[AAA].Value = "111;222;333"; 取值: string value = Request.Cookies[AAA].Value; // value为111 Test2: 给Cooki
    02-09
  • Asp.Net Core 自定义验证属性
      很多时候,在模型上的验证需要自己定义一些特定于我们需求的验证属性。所以这一篇我们就来介绍一下怎么自定义验证属性。  我们来实现一个验证邮箱域名的自定义验证属性,当然,最重要的是需要定义一个继承自ValidationAttribute的类,然后在实现其IsVal
    02-09
  • Asp.Net 之 枚举类型的下拉列表绑定
    有这样一个学科枚举类型:/// 学科 /// /summary public enum Subject {None = 0,[Description("语文")]Chinese = 1,[Description("数学")]Mathematics = 2,[Description("英语")]English = 3,[Description("政治")]Politics = 4,[Description("物理&qu
    02-09
  • [ASP.NET笔记] 1.Web基础知识
         1:http协议:     2:web服务器:     3:静态网页的概念     4:动态网页的概念       http协议:http(hypertext transfer protocol) 即超文本传输协议,这个协议是在internet上进行信息传送的协议任何网页之间要相互沟通,必须要尊循
    02-09
  • ASP.NET邮件发送 .net 发送邮件
      今天做了个ASP.NET做发送邮件功能,发现QQ邮箱好奇怪,当你用QQ邮箱做服务器的时候什么邮件都发送不出去(QQ邮箱除外)。而且爆出这样的错误:"邮箱不可用。 服务器响应为: Error: content rejected.http://mail.qq.com/zh_CN/help/content/rejectedmail.ht
    02-09
  • 由ASP.NET Core根据路径下载文件异常引发的探究
    前言    最近在开发新的项目,使用的是ASP.NET Core6.0版本的框架。由于项目中存在文件下载功能,没有使用类似MinIO或OSS之类的分布式文件系统,而是下载本地文件,也就是根据本地文件路径进行下载。这其中遇到了一个问题,是关于如何提供文件路径的,通
    02-09
  • ASP.NET的运行原理与运行机制 ASP.NET的开发模式包括
    ASP.NET的运行原理与运行机制 ASP.NET的开发模
    在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebForms这种模仿Windows Form编程方式有了很大不同,不再有大量控件和控件生成的大量不够灵活的代码
    02-09
点击排行