一般的在Asp.net裡上傳檔案都是10m左右,要做到大檔案上傳,必須要改web.config,不過改了web.config有時候也上傳不成功,那是每次上傳的檔案太大,瀏覽器在這個過程中會超時,採用分塊上傳的方法就可以避免這種情況。
2.分塊上傳就是利用post的方法,把資料分塊上傳,每塊上傳的資料量少,不會引起超時的問題。不說了,看程式碼吧。
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 runat="server" encType="multipart/form-data" method="post">
2 <div>
3 <INPUT type="file" name="firstFile" runat="server">
4 <asp:Button runat="server" OnClick="Button1_Click" Text="上傳" />
5 <asp:Label 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>
一般的在Asp.net裡上傳檔案都是10m左右,要做到大檔案上傳,必須要改web.config,不過改了web.config有時候也上傳不成功,那是每次上傳的檔案太大,瀏覽器在這個過程中會超時,採用分塊上傳的方法就可以避免這種情況。
2.分塊上傳就是利用post的方法,把資料分塊上傳,每塊上傳的資料量少,不會引起超時的問題。不說了,看程式碼吧。
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 runat="server" encType="multipart/form-data" method="post">
2 <div>
3 <INPUT type="file" name="firstFile" runat="server">
4 <asp:Button runat="server" OnClick="Button1_Click" Text="上傳" />
5 <asp:Label 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>