Asp.net无刷新上传图片,并显示进度条(续)

来源:互联网 发布:逐鹿工具箱是什么软件 编辑:程序博客网 时间:2024/06/03 22:41

上篇文章的错误在于,没有正确的认识服务器上传文件的处理流程,误认为耗时的操作是在保存文件时产生的。事实上,IIS是一次性将上传的文件流放入服务器内存,然后才开始对这个数据流进行分析处理。所以耗时是在数据流传输到服务器的过程中产生的。知道了这一点,下面就要看一下http请求的处理流程,来确定在哪一步时进行干预。


从上图可以知道,应该在httpmodule的beginrequest中来处理进度。引用msdn上的一段话:

HTTP 模块是一个在每次针对应用程序发出请求时调用的程序集。HTTP 模块作为 ASP.NET 请求管线的一部分调用,它们能够在整个请求过程中访问寿命周期事件。因此,HTTP 模块使您有机会检查传入的请求并根据该请求采取操作。它们还使您有机会检查出站响应并修改它。
      在应用程序的 Web.config 文件中注册自定义的 HTTP 模块。当 ASP.NET 创建表示您的应用程序的 HttpApplication 类的实例时,将创建已注册的任何模块的实例。在创建模块时,将调用它的 Init 方法,并且模块会自行初始化。有关更多信息,请参见 ASP.NET 应用程序生命周期概述。
      在模块的 Init 方法内,可以订阅各种应用程序事件(如 BeginRequest 或 EndRequest),这可以通过将事件绑定到模块中已创建的方法来完成。当这些事件被引发时,会调用模块中适当的方法,并且模块可以执行所需的任何逻辑,如身份验证检查或记录请求信息。在事件处理过程中,模块能够访问当前请求的 Context 属性。这使您可以将请求重定向到其他页、修改请求或者执行任何其他请求操作。例如,如果您的模块中包括身份验证检查,则模块可能会检查凭据,如果凭据不正确的话,会重定向到登录页或错误页。否则,当模块的事件处理程序完成运行时,ASP.NET 会调用管线中的下一个进程,这可能是另一个模块,也可能是用于该请求的 HTTP 处理程序(如 .aspx 文件)。


现在解决的思路已经大致清晰了:重新写一个httpmodule,在它的init事件中绑定beginrequest事件。当此事件被触发时,截获HttpWorkerRequest。循环从httpworkrequest中读取数据,分析并保存是文件的数据,同时将进度记录到服务器的缓存中。

1.在init中绑定beginrequest事件

    public void Init(HttpApplication application)    {        //注册页面请求开始事件        application.BeginRequest += new EventHandler(this.Application_BeginRequest);    }
2.获取httpworkrequest对象

    HttpWorkerRequest GetWorkerRequest(HttpContext context)    {        IServiceProvider provider = (IServiceProvider)HttpContext.Current;        return (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));    }

3.循环读取数据流

byte[] brequest = request.GetPreloadedEntityBody();      byte[] bReadStepByte = new byte[iReadStepSize];if (!request.IsEntireEntityBodyIsPreloaded()){while (iLeave > iReadStepSize && request.IsClientConnected())        {        request.ReadEntityBody(bReadStepByte, iReadStepSize);}}

上面列出了核心代码,关于一些细节问题如,如何判断本次请求为文件上传,如何从数据流中找出真正的文件等等,请参考:http://www.cnblogs.com/stg609/archive/2008/07/26/1252231.html

---------------------------------------------------------------------------------------我是分割线------------------------------------------------------------------------------------

总结一下:

这种进度显示的方式,需要客户端对服务器不停地轮询,从做法上很容易被理解,但是效率不高。
如果需要上传大文件并且获取上传进度,目前最好的方法应该是使用RIA方式。RIA技术最典型的应用就是Flash,如:swfupload组件。
另外应用Ria技术的还有微软的silverlight,也可以高效的显示进度条。