IHttpModule 分块上传大文件

1.一般的在Asp.net里上传文件都是10m左右,要做到大文件上传,必须要改web.config,不过改了web.config有时候也上传不成功,那是每次上传的文件太大,浏览器在这个过程中会超时,采用分块上传的方法就可以避免这种情况。
2.分块上传就是利用post的方法,把数据分块上传,每块上传的数据量少,不会引起超时的问题。不说了,看代码吧。


  1 //实现IHttpModule接口
  2     public class HttpUploadModule : IHttpModule
  3     {
  4         public HttpUploadModule()
  5         {
  6 
  7         }
  8 
  9         public void Init(HttpApplication application)
 10         {
 11             //订阅事件
 12             application.BeginRequest += new EventHandler(this.Application_BeginRequest);
 13         }
 14 
 15         public void Dispose()
 16         {
 17         }
 18 
 19         private void Application_BeginRequest(Object sender, EventArgs e)
 20         {
 21             HttpApplication app = sender as HttpApplication;
 22             HttpWorkerRequest request = GetWorkerRequest(app.Context);
 23             Encoding encoding = app.Context.Request.ContentEncoding;
 24 
 25             int bytesRead = 0;  // 已读数据大小
 26             int read;           // 当前读取的块的大小
 27             int count = 8192;   // 分块大小
 28             byte[] buffer;      // 保存所有上传的数据
 29 
 30             if (request != null)
 31             {
 32                 // 返回 HTTP 请求正文已被读取的部分。
 33                 byte[] tempBuff = request.GetPreloadedEntityBody(); //要上传的文件
 34 
 35                 // 如果是附件上传
 36                 if (tempBuff != null && IsUploadRequest(app.Request))    //判断是不是附件上传
 37                 {
 38                     // 获取上传大小
 39                     // 
 40                     long length = long.Parse(request.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength));
 41                     
 42                     buffer = new byte[length];
 43                     count = tempBuff.Length; // 分块大小
 44 
 45                     // 将已上传数据复制过去
 46                     //
 47                     Buffer.BlockCopy(tempBuff,  //源数据
 48                         0,                      //从0开始读
 49                         buffer,                 //目标容器
 50                         bytesRead,              //指定存储的开始位置
 51                         count);                 //要复制的字节数。 
 52 
 53 
 54                     // 开始记录已上传大小
 55                     bytesRead = tempBuff.Length;
 56 
 57                     // 循环分块读取,直到所有数据读取结束
 58                     while (request.IsClientConnected() &&!request.IsEntireEntityBodyIsPreloaded() && bytesRead < length)
 59                     {
 60                         // 如果最后一块大小小于分块大小,则重新分块
 61                         if (bytesRead + count > length)
 62                         {
 63                             count = (int)(length - bytesRead);
 64                             tempBuff = new byte[count];
 65                         }
 66 
 67                         // 分块读取
 68                         read = request.ReadEntityBody(tempBuff, count);
 69 
 70                         // 复制已读数据块
 71                         Buffer.BlockCopy(tempBuff, 0, buffer, bytesRead, read);
 72 
 73                         // 记录已上传大小
 74                         bytesRead += read;
 75 
 76                     }
 77                     if (  request.IsClientConnected() && !request.IsEntireEntityBodyIsPreloaded()  )
 78                     {
 79                         // 传入已上传完的数据
 80                         InjectTextParts(request, buffer);
 81                     }
 82                 }
 83             }
 84         }
 85 
 86 
 87         HttpWorkerRequest GetWorkerRequest(HttpContext context)
 88         {
 89 
 90             IServiceProvider provider = (IServiceProvider)HttpContext.Current;
 91             return (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
 92         }
 93 
 94         /// <summary>
 95         /// 传入已上传完的数据
 96         /// </summary>
 97         /// <param name="request"></param>
 98         /// <param name="textParts"></param>
 99         void InjectTextParts(HttpWorkerRequest request, byte[] textParts)
100         {
101             BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
102 
103             Type type = request.GetType();
104 
105             while ((type != null&& (type.FullName != "System.Web.Hosting.ISAPIWorkerRequest"))
106             {
107                 type = type.BaseType;
108             }
109 
110             if (type != null)
111             {
112                 type.GetField("_contentAvailLength", bindingFlags).SetValue(request, textParts.Length);
113                 type.GetField("_contentTotalLength", bindingFlags).SetValue(request, textParts.Length);
114                 type.GetField("_preloadedContent", bindingFlags).SetValue(request, textParts);
115                 type.GetField("_preloadedContentRead", bindingFlags).SetValue(request, true);
116             }
117         }
118 
119         private static bool StringStartsWithAnotherIgnoreCase(string s1, string s2)
120         {
121             return (string.Compare(s1, 0, s2, 0, s2.Length, true, CultureInfo.InvariantCulture) == 0);
122         }
123 
124         /// <summary>
125         /// 是否为附件上传
126         /// 判断的根据是ContentType中有无multipart/form-data
127         /// </summary>
128         /// <param name="request"></param>
129         /// <returns></returns>
130         bool IsUploadRequest(HttpRequest request)
131         {
132             return StringStartsWithAnotherIgnoreCase(request.ContentType, "multipart/form-data");
133         }
134     }


3.用法
 (1)修改web.config
  

1  < httpModules >
2           < add  name ="HttpUploadModule"
3             type ="HttpModelApp.HttpUploadModule, HttpModelApp"   />
4 
5         </ httpModules >
6         < httpRuntime
7           maxRequestLength ="2000000"
8          executionTimeout ="300"
9       />

  (2)aspx
  

1    < form  id ="form1"  runat ="server"  encType ="multipart/form-data"  method ="post" >
2       < div >
3           < INPUT  id ="firstFile"  type ="file"  name ="firstFile"  runat ="server" >< br  />
4           &nbsp; < asp:Button  ID ="Button1"  runat ="server"  OnClick ="Button1_Click"  Text ="上传"   />< br  />
5           < asp:Label  ID ="Label1"  runat ="server" ></ asp:Label ></ div >
6       </ form >

 (3)aspx.cs
 

 1  protected void Button1_Click(object sender, EventArgs e)
 2          {
 3              //要保存的位置
 4              string strDesPath = "D://";
 5              string strFileName = this.firstFile.PostedFile.FileName;
 6              strFileName =strDesPath + strFileName.Substring(strFileName.LastIndexOf("//"));
 7              //
 8              this.firstFile.PostedFile.SaveAs(strFileName);
 9              this.Label1.Text = "文件保存到了:" + strFileName;
10          }

4.大文件上传的限制
  虽然可以上传大文件,但是这个大小也是有限制的,不能超过2G的大小。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值