【转】让asp.net默认的上传组件支持进度条反映

it2022-05-09  34

本文转自: http://blog.joycode.com/dotey/archive/2005/06/12/53557.aspx

对于web下的上传,实际上更多的时候不用上传太大东西,asp.net默认的上传组件足够用了,美中不足就是没有上传进度反映,所以现在要做的就是在asp.net默认的上传基础上加上进度反映。

关于web上传的原理,曾在以前有深入分析过《asp无组件上传进度条解决方案》《Asp无组件上传带进度条(续) 》,并有写过asp版的无组件上传进度条,在这里就不多赘述。相信很多人都看过思归发的《用ASP.NET上传大文件》,解决的方法是利用隐含的HttpWorkerRequest,用它的GetPreloadedEntityBody 和 ReadEntityBody方法从IIS为ASP.NET建立的pipe里分块读取数据,对于每块分块进行分析并存储为临时文件,相对比较复杂。

要实现进度条的实时反映,核心的技术就是对上传的数据进行“分块”读取,在读取每块数据时记录当前已上传的块数,根据分块的大小,即可知道已上传的大小,根据总大小,即可知道当前上传的进度。具体的技术还是利用隐含的HttpWorkerRequest,用它的GetPreloadedEntityBody 和 ReadEntityBody方法从IIS为ASP.NET建立的pipe里分块读取数据,只不过仅仅是分块和记录已上传块数而已,用不着对已上传的数据进行分析和处理,因为这部分复杂的工作已经由asp.net的上传组件给我们做了。

根据上面所述的原理,具体代码相对很简单,我写了一个例子,用一个专门的进度显示页面(Progress.aspx),通过定时刷新(XmlHttp, FF支持)来获取当前上传的进度信息,并实时反映到上传页面上。

代码下载(解压后给web目录设置虚拟目录为“Upload”即可),其中进度条我是用脚本来实现的,单独的进度条脚本代码:http://www.webuc.net/myproject/progressbar/progressinfo.htm http://www.webuc.net/myproject/progressbar/progressbar.rar

 

using System; using System.Collections; using System.Collections.Specialized; using System.Globalization; using System.IO; using System.Text; using System.Web; using System.Reflection; namespace Openlab.Web.Upload {     /// <summary>     /// 给asp.net默认的上传组件加上进度条反映     /// </summary>     /// <Author>宝玉 (http://www.webuc.net)</Author>     /// <Links>     /// http://www.cnforums.net     /// http://www.communtiyserver.cn     /// http://blog.joycode.com     /// </Links>     public class HttpUploadModule: IHttpModule     {         public HttpUploadModule()         {                     }         public void Init(HttpApplication application)         {             application.BeginRequest += new EventHandler(this.Application_BeginRequest);             application.EndRequest += new EventHandler(this.Application_EndRequest);             application.Error += new EventHandler(this.Application_Error);         }         public void Dispose()         {         }         private void Application_BeginRequest(Object sender, EventArgs e)         {             HttpApplication app = sender as HttpApplication;             HttpWorkerRequest request = GetWorkerRequest(app.Context);             Encoding encoding = app.Context.Request.ContentEncoding;             int bytesRead = 0; // 已读数据大小             int read; // 当前读取的块的大小             int count = 8192; // 分块大小             byte[] buffer; // 保存所有上传的数据             string uploadId; // 唯一标志当前上传的ID             Progress progress; // 记录当前上传的进度信息             if (request != null)             {                 // 返回 HTTP 请求正文已被读取的部分。                 //                 byte[] tempBuff = request.GetPreloadedEntityBody();                                 // 如果是附件上传                 //                 if (                     tempBuff != null                     && IsUploadRequest(app.Request)                     )                 {                     // 获取上传大小                     //                     long length = long.Parse(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));                     // 当前上传的ID,用来唯一标志当前的上传                     // 用此UploadID,可以通过其他页面获取当前上传的进度                     //                     uploadId = app.Context.Request.QueryString["UploadID"];                                         // 开始记录当前上传状态                     //                     progress = new Progress(length, uploadId);                     progress.SetState(UploadState.ReceivingData);                                         buffer = new byte[length];                     count = tempBuff.Length; // 分块大小                     // 将已上传数据复制过去                     //                     Buffer.BlockCopy(tempBuff, 0, buffer, bytesRead, count);                     // 开始记录已上传大小                     //                     bytesRead = tempBuff.Length;                     progress.SetBytesRead(bytesRead);                     SetProgress(uploadId, progress, app.Application);                     // 循环分块读取,直到所有数据读取结束                     //                     while (request.IsClientConnected() &&                         !request.IsEntireEntityBodyIsPreloaded() &&                         bytesRead < length                         )                     {                         // 如果最后一块大小小于分块大小,则重新分块                         //                         if (bytesRead + count > length)                         {                             count = (int)(length - bytesRead);                             tempBuff = new byte[count];                         }                         // 分块读取                         //                         read = request.ReadEntityBody(tempBuff, count);                                                 // 复制已读数据块                         //                         Buffer.BlockCopy(tempBuff, 0, buffer, bytesRead, read);                                                 // 记录已上传大小                         //                         bytesRead += read;                         progress.SetBytesRead(bytesRead);                         SetProgress(uploadId, progress, app.Application);                     }                     if (                         request.IsClientConnected() &&                         !request.IsEntireEntityBodyIsPreloaded()                         )                     {                                         // 传入已上传完的数据                         //                         InjectTextParts(request, buffer);                         // 表示上传已结束                         //                         progress.SetBytesRead(bytesRead);                         progress.SetState(UploadState.Complete);                         SetProgress(uploadId, progress, app.Application);                     }                 }             }         }         /// <summary>         /// 结束请求后移除进度信息         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void Application_EndRequest(Object sender, EventArgs e)         {             HttpApplication app = sender as HttpApplication;             if (IsUploadRequest(app.Request))             {                 SetUploadState(app, UploadState.Complete);                 RemoveFrom(app);             }         }            /// <summary>         /// 如果出错了设置进度信息中状态为“Error”         /// </summary>         /// <param name="sender"></param>         /// <param name="e"></param>         private void Application_Error(Object sender, EventArgs e)         {             HttpApplication app = sender as HttpApplication;             if (IsUploadRequest(app.Request))             {                 SetUploadState(app, UploadState.Error);             }         }         /// <summary>         /// 设置当前上传进度信息的状态         /// </summary>         /// <param name="app"></param>         /// <param name="state"></param>         void SetUploadState(HttpApplication app, UploadState state)         {             string uploadId = app.Request.QueryString["UploadID"];             if (uploadId != null && uploadId.Length > 0)             {                 Progress progress = GetProgress(uploadId, app.Application);                 if (progress != null)                 {                     progress.SetState(state);                     SetProgress(uploadId, progress, app.Application);                 }                    }         }         /// <summary>         /// 设置当前上传的进度信息         /// 根据UploadID记录在Application中         /// </summary>         /// <param name="uploadId"></param>         /// <param name="progress"></param>         /// <param name="application"></param>         void SetProgress(string uploadId, Progress progress, HttpApplicationState application)         {             if (uploadId == null || uploadId == string.Empty || progress == null)                 return;             application.Lock();             application["OpenlabUpload_" + uploadId] = progress;             application.UnLock();         }         /// <summary>         /// 从Application中移出进度信息         /// </summary>         /// <param name="app"></param>         void RemoveFrom(HttpApplication app)         {             string uploadId = app.Request.QueryString["UploadID"];             HttpApplicationState application = app.Application;             if (uploadId != null && uploadId.Length > 0)             {                 application.Remove("OpenlabUpload_" + uploadId);             }         }         /// <summary>         /// 根据UploadID获取上传进度信息         /// </summary>         /// <param name="uploadId"></param>         /// <param name="application"></param>         /// <returns></returns>         public static Progress GetProgress(string uploadId, HttpApplicationState application)         {             Progress progress = application["OpenlabUpload_" + uploadId] as Progress;             return progress;         }         HttpWorkerRequest GetWorkerRequest(HttpContext context)         {             IServiceProvider provider = (IServiceProvider)HttpContext.Current;             return (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));         }         /// <summary>         /// 传入已上传完的数据         /// </summary>         /// <param name="request"></param>         /// <param name="textParts"></param>         void InjectTextParts(HttpWorkerRequest request, byte[] textParts)         {             BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;                         Type type = request.GetType();                         while ((type != null) && (type.FullName != "System.Web.Hosting.ISAPIWorkerRequest"))             {                 type = type.BaseType;             }             if (type != null)             {                 type.GetField("_contentAvailLength", bindingFlags).SetValue(request, textParts.Length);                 type.GetField("_contentTotalLength", bindingFlags).SetValue(request, textParts.Length);                 type.GetField("_preloadedContent", bindingFlags).SetValue(request, textParts);                 type.GetField("_preloadedContentRead", bindingFlags).SetValue(request, true);             }         }         private static bool StringStartsWithAnotherIgnoreCase(string s1, string s2)         {             return (string.Compare(s1, 0, s2, 0, s2.Length, true, CultureInfo.InvariantCulture) == 0);         }         /// <summary>         /// 是否为附件上传         /// 判断的根据是ContentType中有无multipart/form-data         /// </summary>         /// <param name="request"></param>         /// <returns></returns>         bool IsUploadRequest(HttpRequest request)         {             return StringStartsWithAnotherIgnoreCase(request.ContentType, "multipart/form-data");         }     } }

转载于:https://www.cnblogs.com/feima-lxl/archive/2008/07/12/1241256.html

相关资源:数据结构—成绩单生成器

最新回复(0)