随着ajax技术的流行以及用户体验得到越来越高的重视,各种注视用户体验的程序出现,比如带进度条的文件上传,看了网上很多资料还没找到真正意义上的ASP.NET实现进度条上传(可能是我没找到),下面我来跟大家分享一下我实现的这个程序。

最终实现的效果图如下:(备注:Firefox3.6下的截图)

 

  先解释一下这个程序,该程序采用了jquery框架,实现了小文件上传,不超过80Mb,可以在web.config文件中进行相应的配置,但是有个最大值,具体需要查看msdn,下一篇文章我将会实现大文件上传,下一篇文章估计得过段时间,因为接下来这几天我需要忙着去面试。另外,开发环境采用visual studio 2010 .net framework 4.0,运行的时候大家注意一下是否满足要求,好了,下面直入正题。

  先来看看实现原理。基本原理:一个页面进行文件上传,另外一个页面去监听这个文件上传了多少。

  这里面有两个地方需要解释一下:第一个,如何知道监听的这个文件就是上传的这个文件?实现机制很简单,就是让asp.net产生一个唯一的guid,这个id序号是唯一的,通过ajax取出来赋值给一个隐藏字段;第二个,如何获取guid标志的文件信息?通过asp.net缓存机制实现,上传的过程中,不断的将上传信息往缓存里面写,直到文件上传完成,而在另外一个通过guid获取缓存的信息,信息包括你想要的信息,比如上传了多少字节、消耗了多长时间等。好了,要点就解释到这里,有疑问的话给我留言。

下面来说说具体的实现:

文件目录结构如下:

index.htm就是文件上传页面,提交form给UploadHandler目录下的Default.aspx,以实现文件上传。

ProgressHandler目录下三个文件为Abort.ashx、GenericGuid.ashx,Handler.ashx功能分别为:根据Guid取消正在上传的文件,生成Guid,根据Guid获取上传信息。

第一步:建立index.htm页面,这个上传页面,需要注意的就是需要一个隐藏的iframe,并且名字为form提交的目标。

View Code
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
3  <html xmlns="http://www.w3.org/1999/xhtml">
4  <head>
5 <title>ASP.NET Ajax文件上传进度条示例</title>
6 <meta name="author" content="李检全" />
7 <link href="Styles/base.css" rel="stylesheet" type="text/css" />
8 <script src="Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
9 <script src="Scripts/jquery-ui-1.8.2.custom.min.js" type="text/javascript"></script>
10 <script src="Scripts/ljq.lib.js" type="text/javascript"></script>
11 <script src="Scripts/Ajax/GuidGet.js" type="text/javascript"></script>
12 <script src="Scripts/Ajax/ajax-progress-upload.js" type="text/javascript"></script>
13  </head>
14  <body>
15 <div id="upload_demo">
16 <div class="title">ASP.NET Ajax 文件上传进度条示例</div>
17 <form action="UploadHandler/Default.aspx" enctype="multipart/form-data" method="post" target="upload_hidden_iframe">
18 <input id="guid" name="guid" value="" type="hidden"/>
19 <p>*本程序适合小文件上传,不超过80Mb</p>
20 <p>文件地址</p>
21 <input name="upload_file" type="file" />
22 <br />
23 <p>文件描述</p>
24 <textarea name="description_file" ></textarea>
25 <br />
26 <br />
27 <input type="submit" value="上传文件"/>
28 </form>
29 </div>
30 <div id="back_panel"></div>
31 <div id="upload_panel">
32 <div id="upload_title">文件上传</div>
33 <div id="upload_content">
34
35 <ul>
36 <li id="finished_percent">正在准备上传...</li>
37 <li><div id="upload_bar"><div id="upload_progress"></div></div></li>
38 <li id="upload_speed"></li>
39 <li id="upload_costTime"></li>
40 <li id="upload_fileSize"></li>
41 <li id="upload_fileName"></li>
42 </ul>
43
44 <div id="upload_detail"></div>
45 <div id="upload_choose">
46 <span id="upload_cancel">取消</span><span id="upload_submit">确定</span>
47 </div>
48 </div>
49 </div>
50 <iframe name="upload_hidden_iframe" style="display:none;">
51
52 </iframe>
53
54
55  </body>
56  </html>

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

View Code

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

View Code
1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Web;
5  using System.Web.UI;
6  using System.Web.UI.WebControls;
7  /*========================================================================================
8 *
9 * Developed By 李检全
10 *
11 * Date 2011-03-10
12 *
13 * Contact Me
14 *
15 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
16 *
17 * Email lijianquan07@gmail.com
18 *
19 * QQ 55643287
20 *
21 * Copyright (c) 李检全 All Rights Reserved
22 *
23 * =======================================================================================
24  */
25  public partial class UploadHandler_Default : System.Web.UI.Page
26 {
27 protected void Page_Load(object sender, EventArgs e)
28 {
29 string guid = Request.Params["guid"];
30 UploadUtil utilHelp = new UploadUtil(this, guid);
31 utilHelp.Upload();
32 }
33 }

上传核心代码:

View Code
1 using System;
2  using System.Collections.Generic;
3  using System.Linq;
4  using System.Web;
5  using System.IO;
6  using System.Configuration;
7  using System.Web.UI;
8  using System.Web.Caching;
9  using System.Threading;
10  /*========================================================================================
11 *
12 * Developed By 李检全
13 *
14 * Date 2011-03-10
15 *
16 * Contact Me
17 *
18 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
19 *
20 * Email lijianquan07@gmail.com
21 *
22 * QQ 55643287
23 *
24 * Copyright (c) 李检全 All Rights Reserved
25 *
26 * =======================================================================================
27  */
28  public class UploadUtil
29 {
30 private Stream reader;
31 private FileStream fStream;
32 private const int BUFFERSIZE = 10000;
33 private string filePath =new Page().Server.MapPath(ConfigurationManager.AppSettings["upload_folder"]);
34 private Page page;
35 private string guid;
36 public UploadUtil(Page page, string guid)
37 {
38 this.page = page;
39 this.guid = guid;
40 }
41 public void Upload()
42 {
43 if (this.page.Request.Files.Count > 0)
44 {
45 this.doUpload(this.page.Request.Files[0]);
46 }
47 else
48 {
49 return;
50 }
51 }
52 private void doUpload(HttpPostedFile postedFile)
53 {
54 bool _abort = false;
55 string _filePath = this.filePath + DateTime.Now.ToFileTime()+"//";
56 if (!Directory.Exists(_filePath))
57 {
58 Directory.CreateDirectory(_filePath);
59 }
60 string _fileName = postedFile.FileName;
61 DownloadingFileInfo info = new DownloadingFileInfo(_fileName,postedFile.ContentLength,postedFile.ContentType);
62 object fileObj = HttpContext.Current.Cache[this.guid];
63 if (fileObj != null)
64 {
65 HttpContext.Current.Cache.Remove(this.guid);
66 }
67 HttpContext.Current.Cache.Add(this.guid, info, null, DateTime.Now.AddDays(1), TimeSpan.Zero, CacheItemPriority.AboveNormal, null);
68 DateTime begin=DateTime.Now.ToLocalTime();
69 fStream = new FileStream(_filePath+_fileName,FileMode.Create);
70 reader = postedFile.InputStream;
71 byte []buffer=new byte[BUFFERSIZE];
72 int len = reader.Read(buffer,0,BUFFERSIZE);
73
74 while (len > 0&&!_abort)
75 {
76 fStream.Write(buffer,0,len);
77 DateTime end = DateTime.Now.ToLocalTime();
78 info.CostTime = (long)(end - begin).TotalMilliseconds;
79 info.FileFinished += len;
80
81 //模拟延时用,实际应用的时候注销他
82   Thread.Sleep(10);
83
84 HttpContext.Current.Cache[this.guid] = info;
85 _abort=((DownloadingFileInfo)HttpContext.Current.Cache[this.guid]).Abort;
86 len = reader.Read(buffer,0,BUFFERSIZE);
87 }
88
89 reader.Close();
90 fStream.Close();
91 if (_abort)
92 {
93 if (File.Exists(_filePath + _fileName))
94 {
95 File.Delete(_filePath + _fileName);
96 }
97 }
98 }
99
100 }

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

View Code
1 <%@ WebHandler Language="C#" Class="Handler" %>
2
3  using System;
4  using System.Web;
5  using System.Xml.Linq;
6  using System.Web.Caching;
7  /*========================================================================================
8 *
9 * Developed By 李检全
10 *
11 * Date 2011-03-10
12 *
13 * Contact Me
14 *
15 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
16 *
17 * Email lijianquan07@gmail.com
18 *
19 * QQ 55643287
20 *
21 * Copyright (c) 李检全 All Rights Reserved
22 *
23 * =======================================================================================
24  */
25  public class Handler : IHttpHandler {
26
27 public void ProcessRequest (HttpContext context) {
28 context.Response.ContentType = "application/xml";
29 context.Response.Charset = "utf-8";
30 string guid = context.Request.Form["guid"];
31 DownloadingFileInfo info = context.Cache[guid] as DownloadingFileInfo;
32 XDocument doc = new XDocument();
33 XElement root = new XElement("root");
34 if (info != null)
35 {
36 XElement fileName = new XElement("fileName", info.FileName);
37 XElement fileFinished = new XElement("fileFinished", info.FileFinished);
38 XElement fileSize = new XElement("fileSize", info.FileSize);
39 XElement costTime = new XElement("costTime", info.CostTime);
40 XElement fileState = new XElement("fileState", info.FileState);
41 XElement speed = new XElement("speed",info.Speed);
42 XElement percent = new XElement("percent",info.Percent);
43 XElement abort = new XElement("abort",false);
44 root.Add(fileName);
45 root.Add(fileFinished);
46 root.Add(fileSize);
47 root.Add(costTime);
48 root.Add(fileState);
49 root.Add(speed);
50 root.Add(percent);
51 if (info.Abort)
52 {
53 abort.Value = info.Abort.ToString();
54 context.Cache.Remove(guid);
55 }
56 if (info.FileState == "finished")
57 {
58 context.Cache.Remove(guid);
59 }
60
61
62 }
63 else
64 {
65 XElement none = new XElement("none","no file");
66 root.Add(none);
67 }
68 doc.Add(root);
69 context.Response.Write(doc.ToString());
70 context.Response.End();
71 }
72
73 public bool IsReusable {
74 get {
75 return false;
76 }
77 }
78
79 }

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

View Code
1 <%@ WebHandler Language="C#" Class="Abort" %>
2
3  using System;
4  using System.Web;
5  using System.Xml.Linq;
6  /*========================================================================================
7 *
8 * Developed By 李检全
9 *
10 * Date 2011-03-10
11 *
12 * Contact Me
13 *
14 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
15 *
16 * Email lijianquan07@gmail.com
17 *
18 * QQ 55643287
19 *
20 * Copyright (c) 李检全 All Rights Reserved
21 *
22 * =======================================================================================
23  */
24
25  public class Abort : IHttpHandler {
26
27 public void ProcessRequest (HttpContext context) {
28 context.Response.ContentType = "application/xml";
29 context.Response.Charset = "utf-8";
30 string guid = context.Request.Form["guid"];
31 bool abort = string.IsNullOrEmpty(context.Request.Form["abort"]) ? false : true;
32 DownloadingFileInfo info = context.Cache[guid] as DownloadingFileInfo;
33 if (info != null)
34 {
35 info.Abort = abort;
36 context.Cache[guid] = info;
37 }
38 XDocument doc = new XDocument();
39 XElement root = new XElement("root");
40 XElement flag = new XElement("flag",info==null?"false":"true");
41 root.Add(flag);
42 doc.Add(root);
43 context.Response.Write(doc.ToString());
44 context.Response.End();
45 }
46
47 public bool IsReusable {
48 get {
49 return false;
50 }
51 }
52
53 }

好了,下面就是编写javascript脚本了,我引用了jquery这个框架,另外还用了ui框架。

核心代码是ajax-progress-upload.js文件,另外还有一个获取guid的文件。

View Code
1 /*========================================================================================
2 *
3 * Developed By 李检全
4 *
5 * Date 2011-03-10
6 *
7 * Contact Me
8 *
9 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
10 *
11 * Email lijianquan07@gmail.com
12 *
13 * QQ 55643287
14 *
15 * Copyright (c) 李检全 All Rights Reserved
16 *
17 * =======================================================================================
18  */
19 $(document).ready(function () {
20 var _guid_url = "ProgressHandler/GenerateGuid.ashx";
21 var _progress_url = "ProgressHandler/Handler.ashx";
22 var _abort_url = "ProgressHandler/Abort.ashx";
23 var _target = "#guid";
24 var _guid = "";
25 var _cancel = false;
26 var _timer;
27 LJQ.setGuid(_target, _guid_url);
28 $("#upload_panel").draggable({ handle: "#upload_title" });
29 $("#upload_choose span").hover(function () {
30 $(this).css({
31 "color": "#f6af3a",
32 "border": "1px solid #e78f08"
33 });
34 }, function () {
35 $(this).css({
36 "color": "#1c94cd",
37 "border": "1px solid #ddd"
38 });
39 });
40 $("#upload_cancel").click(function () {
41 $.ajax({
42 url: _abort_url,
43 data: { guid: _guid, abort: true },
44 dataType: "xml",
45 type: "post",
46 success: function () {
47
48 $("#upload_panel").fadeOut('fast');
49 $("#back_panel").fadeOut(1000);
50 window.clearInterval(_timer);
51 }
52 });
53
54
55 });
56 $("#upload_submit").click(function () {
57 $("#upload_panel").fadeOut('fast');
58 $("#back_panel").fadeOut("1000");
59 });
60 $("form").submit(function () {
61 _guid = $(_target).val();
62 if ($("input[name='upload_file']").val() == "") {
63 alert("未指定上传文件!");
64 return false;
65 }
66 $("#upload_progress").css("width", "0%");
67 $("#finished_percent").html("准备上传...");
68 $("#upload_speed").html("");
69 $("#upload_fileName").html("");
70 $("#upload_fileSize").html("");
71 $("#upload_costTime").html("");
72 var _option = {
73 url: _progress_url,
74 data: { guid: _guid },
75 dataType: "xml",
76 type: "post",
77 beforeSend: function () {
78 $("#back_panel").fadeTo('fast', '0.5');
79 $("#upload_panel").fadeIn('1000');
80 },
81 success: function (response) {
82
83 if ($(response).find("root abort").text() == "true") {
84 $("#upload_panel").fadeOut('fast');
85 $("#back_panel").fadeOut(1000);
86 window.clearInterval(_timer);
87 }
88
89 else if ($(response).find("root none").text() == "no file") {
90
91 }
92 else {
93 var _percent = ($(response).find("root percent").text() * 100);
94 var _speed = $(response).find("root speed").text();
95 var _fileSize = $(response).find("root fileSize").text();
96 var _upload_costTime = $(response).find("root costTime").text();
97 if (parseInt(_speed) < 1024) {
98 _speed = LJQ.toFix(_speed) + "Kb";
99 } else {
100 _speed = LJQ.toFix(_speed / 1024) + "Mb";
101 }
102
103 if (parseInt(_fileSize) / 1024 < 1024) {
104 _fileSize = LJQ.toFix(_fileSize / 1024) + "Kb";
105 } else if (parseInt(_fileSize) / 1024 / 1024 < 1024) {
106 _fileSize = LJQ.toFix(_fileSize / 1024 / 1024) + "Mb";
107 } else {
108 _fileSize = LJQ.toFix(_fileSize / 1024 / 1024 / 1024) + "Gb";
109 }
110
111 if (_upload_costTime < 1000) {
112 _upload_costTime = _upload_costTime + "毫秒";
113 } else if (_upload_costTime / 1000 < 60) {
114 _upload_costTime = parseInt(_upload_costTime / 1000) + "" + _upload_costTime % 1000 + "毫秒";
115 } else {
116 _upload_costTime = parseInt(_upload_costTime / 1000 / 60) + "" + parseInt((_upload_costTime % 60000) / 1000) + "" + _upload_costTime % 1000 + "毫秒";
117 }
118 $("#upload_progress").css("width", parseInt(_percent) + "%");
119 $("#finished_percent").html("完成百分比:" + LJQ.toFix(_percent) + "%");
120 $("#upload_speed").html("上传速度:" + _speed + "/sec");
121 $("#upload_fileName").html("文件名称:" + $(response).find("root fileName").text());
122 $("#upload_fileSize").html("文件大小:" + _fileSize);
123 $("#upload_costTime").html("上传耗时:" + _upload_costTime);
124 if (_percent >= 100) {
125
126 window.clearInterval(_timer);
127 $("#finished_percent").html("<span style='color:green;'>文件上传完成</span>");
128 }
129 if (_cancel) {
130 window.clearInterval(_timer);
131 }
132 }
133
134 },
135 error: function () { }
136 };
137
138 _timer = window.setInterval(function () { $.ajax(_option); }, 1000);
139
140 });
141
142 });

View Code
1 /*========================================================================================
2 *
3 * Developed By 李检全
4 *
5 * Date 2011-03-10
6 *
7 * Contact Me
8 *
9 * Address 辽宁省大连市开发区辽河西路18号大连民族学院二教631工作室
10 *
11 * Email lijianquan07@gmail.com
12 *
13 * QQ 55643287
14 *
15 * Copyright (c) 李检全 All Rights Reserved
16 *
17 * =======================================================================================
18  */
19 (function () {
20 if (!window['LJQ']) {
21 window['LJQ'] = {};
22 }
23 function setGuid(target, url) {
24 var _option = {
25 url: url,
26 dataType: "xml",
27 type: "post",
28 success: function (response) {
29 $(target).val($(response).find("root guid").text());
30 }
31 };
32 $.ajax(_option);
33 }
34 window['LJQ']['setGuid'] = setGuid;
35 function getProgress(guid) {
36 var _option = {};
37 }
38 })();

好了,程序介绍到这里了。第一次在博客园写文章,不足之处请大家谅解,本人能力有限,不对之处请大家指出,有疑问的可以给我留言,我会尽力而为。

源程序下载地址:点击下载

作者: 检全 发表于 2011-03-10 18:09 原文链接

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"