最近做项目中遇到很多问题,比如带进度条的文件上传,看了网上很多资料还没找到真正意义上的ASP.NET实现进度条上传(可能是我没找到),下面我来跟大家分享一下我实现的这个程序。
首先看下界面效果,当然你可以完全修改界面为你自己所用。
先解释一下这个程序,该程序采用了jquery框架,实现了小文件上传,不超过80Mb,可以在web.config文件中进行相应的配置,但是有个最大值,具体需要查看msdn。开发环境采用visual studio 2013 .net framework 4.5,运行的时候大家注意一下是否满足要求,好了,下面直入正题。
先来看看实现原理。基本原理:一个页面进行文件上传,另外一个页面去监听这个文件上传了多少。
这里面有两个地方需要解释一下:第一个,如何知道监听的这个文件就是上传的这个文件?实现机制很简单,就是让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提交的目标。
ASP.NET Ajax文件上传进度条示例 ASP.NET Ajax 文件上传进度条示例文件上传
- 正在准备上传...
取消确定
第二步,创建GenerateGuid.ashx文件,作用就是生成唯一的Guid。
<%@ WebHandler Language="C#" Class="ProgressHandler.Handler" %> using System; using System.Web; using System.Xml.Linq; namespace ProgressHandler { public class Handler : IHttpHandler { ////// 获得上传文件的GUID /// /// 当前请求实体 ///2015-06-28 ///FreshMan 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 { ////// 获得上传文件的进度 /// /// 当前请求实体 ///2015-06-28 ///FreshMan 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 { ////// 取消上传处理程序 /// /// 当前请求实体 ///2015-06-28 ///FreshMan 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("文件上传完成");
}
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