利用HTTP上传不能超过2G的文件

Code
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">

4           <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="上传" />

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的大小。

还有啊,大家不要忘记了导入命名空间.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Text;
using System.Web;
using System.Reflection;
web.config文件如下
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
   <!--
             设置 compilation debug="true" 将调试符号插入
             已编译的页面中。但由于这会
             影响性能,因此只在开发过程中将此值
             设置为 true。
         -->
   <compilation debug="true" />
   <!--
             通过 <authentication> 节可以配置 ASP.NET 使用的
             安全身份验证模式,
             以标识传入的用户。
         -->
   <authentication mode="Windows" />
   <!--
             如果在执行请求的过程中出现未处理的错误,
             则通过 <customErrors> 节可以配置相应的处理步骤。具体说来,
             开发人员通过该节可以配置
             要显示的 html 错误页
             以代替错误堆栈跟踪。
         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
             <error statusCode="403" redirect="NoAccess.htm" />
             <error statusCode="404" redirect="FileNotFound.htm" />
         </customErrors>
         -->
   <httpModules>
   <add name="HttpUploadModule"
       type="HttpModelApp.HttpUploadModule, HttpModelApp" />
   </httpModules>
   <httpRuntime
     maxRequestLength="2000000"
     executionTimeout="300"
/>
</system.web>
</configuration>

posted @ 2012-03-09 18:42  (二少)在南极  阅读(3543)  评论(0编辑  收藏  举报