回覆列表
  • 1 # 每天一個好影片

    一般的在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>

  • 中秋節和大豐收的關聯?
  • 即將跟主帥一對一,曾繁日在個人媒體上發文求助,並給自己打氣“硬一點”,你怎麼看?