zoukankan      html  css  js  c++  java
  • Extjs+Asp.net实现上传大文件带实时进度条

     主要是为了记录自己的学习过程,整理自己的思路以便以后的学习。

    首先先说一下整体的思路。

    我门都知道,asp自带的上传文件是先将上传的文件整个读取到内存然后在写入磁盘的。如果文件很大的话,上传时就会出现页面停滞,没有任何反映。用户根本不知道页面在做什么,也不知道是否在上传,上传了多少?这样的用户体验是很差的。

    所以我门需要实现一个进度条来反映文件上传的进度,可以反映文件写入的进度。具体的思路是通过asp.net提供的HttpModule(Http模块)中的init方法内订阅各种应用程序事件(如BeginRequest事件和EndRequest事件),而Application.BeginRequest事件始终是http请求处理期间第一个发生的事件。我门要做的就是在BefionRequest事件中截取上传请求,然后做文件分块上传,就可以获得文件上传的进度了。

    然后我们建一步一步来完成这个功能吧。

    1.要写module类必须先配置web.config。注册模块

      在web.config中的<System.Web>节中添加模块:

    格式为

    <httpModules>   
              <add name="modulename" type="classname,assemblyname" />      
        </httpModules>   

      根据上面的格式我配置的节:

      <httpModules>   
             <add name="MyHttpModule1" type="MyHttpModule" />      
      </httpModules>

    2.然后根据配置的模块创建一个相同的类MyHttpModule.

         注意这个类必须实现IHttpModule接口,这样才能实现HttpModule的基本功能。然后在类中添加模块的初始化事件和处理事件。

    public void Dispose()
    {
      }

    public void Init(HttpApplication application)
    {

    //订阅我门需要的事件

    //订阅BeginRequest事件

    application.BegionRequest+=new EventHandler(this.Aplication_BeginRequest);
       }

    3.添加事件void Application_BeginRequest(object sender, EventArgs e)

      //在这写代码实现我门需要的功能

    1. 首先先要判断是否为上传文件

      因为需要上传文件的FORM表单都必须设置FORM表彰中的enctype属性为multipart/form-data(如果我们使用 FileUpload组件,则会在编译时自动替我们加上这个属性)。所以我们只需要判断HTTP请求头的ContentType值是否为 multipart/form-data即可,如果不是,我们就没必要对该请求进行处理了。
          enctype="multipart/form-data实际上是一种编码规范(默认的话是application/x-www-form- urlencoded,该方式不适合大块二进制数据传输),该编码方式的基本思想就是用分隔符来分隔数据项,分隔符如“-----------------------------7d87d1cc0a88”。

    1. 2.  获取HTTP请求总长度和HttpWorkerRequest对象

    通过获取HttpApplication.Request.ContentLength属性便可获取HTTP请求内容的总长度,以便我们后来的使用。再声明一个具体的当前Http请求实例

    IServiceProvider provider = (IServiceProvider)HttpContext.Current;

                HttpWorkerRequest request = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));

     4. 分块读取请求并存储数据。

    使用HttpWorkerRequest.GetPreloadedEntityBody()方法第一次获取Http请求部分。HttpWorkerRequest.ReadEntityBody()读取剩余数据。

    while (iLeave > iReadStepSize && request.IsClientConnected())
    //首先判断剩余的请求大小是否大于iReadStepSize

        iRead = request.ReadEntityBody(bReadStepByte, iReadStepSize);   /*读取最大字节数为iReadStepSize的用户请求到bReadStepByte数组中*/     

        对文件内容的处理

          iLeave -= iRead;
        }
        if (iLeave > 0 && request.IsClientConnected())
            {    iRead = request.ReadEntityBody(bReadStepByte, iLeave);

      /*最后还剩一部分,因为小于iReadStepSize,所以写在循环外*/
       
          对文件内容的处理
    }

    我们真正需要上传的部分是文件内容部分。而第一次读取的内容是包括请求头等内容的。我门需要把文件内容给截取出来。

    01 -----------------------------7d87d1cc0a88
     02 Content-Disposition: form-data; name="tbVideoName"
     03
     04 vnm
     05 -----------------------------7d87d1cc0a88
     06 Content-Disposition: form-data; name="file"; filename="C:Documents and Settingsstg609妗岄潰浣冲彞.txt"
     07 Content-Type: text/plain
     08
     09 这里是我上传的文本内容
     10 -----------------------------7d87d1cc0a88
     11 Content-Disposition: form-data; name="__EVENTVALIDATION"
     12
     13 /wEWBgK0g/7JCQLrqYKOBgKj5pr/CAKBmOPQBQLY14yNBQKmmtpNX1cOVXyqN8xEER3ZXbnXzsUwVVo=
     14 -----------------------------7d87d1cc0a88--

    (09)行就是我门需要的文件内容。

    5.获得上传进度。

       1.首先需要在上传也面声明一个隐藏域保存一个全局唯一的UploadID。这个变量相当于一个标志。只要获得这个标志就可以操作获得上传的进度。

    2.写一个类来保存进度。然后将这个类保存到cahce中。以UploadID作为cache的key。

    3.使用AJAX的XmlHttpRequest对象来想服务器发送异步请求。

  • 相关阅读:
    Spinnerd的功能和用法
    vagrant up ----失败 问题解决
    Yii2.0基础框架
    linux上nginx新建站点
    vagrant(二)配置文件vagrantfile详解 以及安装php、nginx、mysql
    vagrant(一)初识与安装
    cmd 使用gii的命令行用法
    mysql 使用shell时出现 ERROR 2006 (HY000): MySQL server has gone away 解决方法
    c++ virtual总结
    kartikgridGridView 合计,多选,导出excel,header修改 等方法集合!
  • 原文地址:https://www.cnblogs.com/tanzhen/p/4024503.html
Copyright © 2011-2022 走看看